﻿
Imports System.Threading
Imports System.Security.Cryptography
Imports System.IO
Imports System.Windows
Imports System.Collections.Generic
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Colors
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.LayerManager
Imports Autodesk.windows
Imports OfficeOpenXml

Public Class CLDS_RCMS
    Implements Autodesk.AutoCAD.Runtime.IExtensionApplication
    '
    ' 13.09     30/09/2013  Original
    ' 14.05     07/05/2014  R2.03 release candidate
    ' 14.05.2   13/05/2014  Fix mis-handling of building with no allocated number range
    '                       Fix problem with deleting previously added WP when adding next
    ' 14.06.1   06/06/2014  Fix problem when building/campus not found from drawing name
    '                       Include PROJECTNAME in dialog connection label
    ' 14.06.2   25/06/2014  Allow sync if duplicate cable IDs (OK/Cancel to confirm)
    '                       Make cable and zone fields uppercase
    '                       Validate cable ID format
    '                       Add CLDS_RCMS and PROJECTNAME to "Big A" AutoCAD application menu
    '                       Change auto-load to AutoCAD start rather than on demand (so that Big A menu is populated)
    ' 14.07.1   01/07/2014  Add colour highlighting to WP model combo-box
    ' 14.08.1   04/08/2014  Add "NEW" mode to support update of WP blocks containing "#" as if they were inserts
    '                       Enable auto-fill on update if all cables currently blank
    '                       Treat "#" in FPID or floor as error when creating list view
    '                       Cable errors (apart from duplicates) prevent synchronization
    ' 14.10.1   23/10/2014  Set zone when updating WP with no cables (i.e. auto-fill enabled)
    ' 14.11.1   14/11/2014  Use CLDS_FindFile to find WP-RCMS and ZONE block to ensure Project File Search Path used
    '                       Pop up message box if WP-RCMS or ZONE block not found
    '                       Prepend "ZONE-" to zone field if necessary when auto-filling cables
    ' 14.11.2   19/11/2014  Generate new FP number when text changes in floor/room combo-box, not just when index selected
    '
    Public v_no As String = "14.11.2"                           ' Module version (string)
    Public v_verno As Integer = 1411                            ' Module version (numeric)
    Public v_date As String = "19th November 2014"               ' Module date
    Public v_minrs As Integer = 1405                            ' Minimum RCMS V9 rule-set version
#Region "Private declarations"
    Friend Shared CMAPI As Cloudis.CMAPI_Client = Nothing       ' CMPIC Servlet communications
    Friend Shared CMERR As String = ""                          ' CMPIC Servlet error
    Friend Shared v_props As RCMS_Drawing_Properties = Nothing  ' CMPIC Servlet communication parameters
    Friend Shared v_prefs As New RCMS_Preferences               ' Preferences
    Friend Shared p_palette As  _
        Autodesk.AutoCAD.Windows.PaletteSet = Nothing           ' RCMS palette set
    Friend Shared p_palguid As _
        New Guid("2BEF9D70-1D4D-4768-9B16-3C8F9FB47398")        ' RCMS palette GUID
    Friend Shared p_rcmsdialog As RCMS_Container = Nothing      ' RCMS dialog
    Friend Shared p_currdocs As Document = Nothing

    Private x_udkey As String = "RCMS_Document_Data"            ' Document UserData HashTable key

    Private b_table As Collection = Nothing                     ' Cache block table records
    Private tokens As Collection = Nothing

    Private fpBlock As ObjectId = ObjectId.Null                 ' Current FP block for insert/update

    Private mUCSWCS As Matrix3d                                 ' UCS->WCS transformation matrix
    Private bUCSWCS As Boolean = False                          ' True when mUCSWCS valid
    Private mWCSUCS As Matrix3d                                 ' WCS->UCS transformation matrix
    Private bWCSUCS As Boolean = False                          ' True when mWCSUCS valid

    Private dWP As System.Collections.Generic.Dictionary(Of String, String())  ' WP IDs and port counts

#End Region
#Region "Properties"
    Public ReadOnly Property pCMAPI() As Cloudis.CMAPI_Client
        Get
            Return CMAPI
        End Get
    End Property
    Public Property pCMERR() As String
        Get
            Return CMERR
        End Get
        Set(ByVal value As String)
            CMERR = value
        End Set
    End Property
    Public Property pProps() As RCMS_Drawing_Properties
        Get
            Return v_props
        End Get
        Set(ByVal value As RCMS_Drawing_Properties)
            v_props = value
        End Set
    End Property
    Public Property pPrefs() As RCMS_Preferences
        Get
            Return v_prefs
        End Get
        Set(ByVal value As RCMS_Preferences)
            v_prefs = value
        End Set
    End Property
    Public ReadOnly Property pPalette() As Autodesk.AutoCAD.Windows.PaletteSet
        Get
            Return p_palette
        End Get
    End Property
    Public Property pRCMSDialog() As RCMS_Container
        Get
            Return p_rcmsdialog
        End Get
        Set(ByVal value As RCMS_Container)
            p_rcmsdialog = value
        End Set
    End Property
    Public Property VersionStr() As String
        Get
            Return v_no
        End Get
        Set(ByVal value As String)
            v_no = value
        End Set
    End Property
    Public Property VersionNo() As Integer
        Get
            Return v_verno
        End Get
        Set(ByVal value As Integer)
            v_verno = value
        End Set
    End Property
    Public Property VersionDate() As String
        Get
            Return v_date
        End Get
        Set(ByVal value As String)
            v_date = value
        End Set
    End Property
    Public Property MinRSNo() As Integer
        Get
            Return v_minrs
        End Get
        Set(ByVal value As Integer)
            v_minrs = value
        End Set
    End Property
    Public Property BlockCache() As Collection
        Get
            Return b_table
        End Get
        Set(ByVal value As Collection)
            b_table = value
        End Set
    End Property
    Public ReadOnly Property pTokens() As Collection
        Get
            Return tokens
        End Get
    End Property
    Public Property pWP() As System.Collections.Generic.Dictionary(Of String, String())
        Get
            Return dWP
        End Get
        Set(ByVal value As System.Collections.Generic.Dictionary(Of String, String()))
            dWP = value
        End Set
    End Property
#End Region
#Region "Auto-load methods"
    Public Sub Initialize() Implements IExtensionApplication.Initialize
        AddHandler ComponentManager.ApplicationMenu.Opening, AddressOf ApplicationMenu_Opening
    End Sub
    Public Sub Terminate() Implements IExtensionApplication.Terminate
        RemoveHandler ComponentManager.ApplicationMenu.Opening, AddressOf ApplicationMenu_Opening
    End Sub
    Public Sub ApplicationMenu_Opening(ByVal sender As Object, ByVal e As EventArgs)
        RemoveHandler ComponentManager.ApplicationMenu.Opening, AddressOf ApplicationMenu_Opening
        AddApplicationMenu()
    End Sub
    Public Sub AddApplicationMenu()
        Dim menu As ApplicationMenu = ComponentManager.ApplicationMenu
        If (Not (menu Is Nothing)) AndAlso (Not menu.MenuContent Is Nothing) Then
            Dim mi(2) As ApplicationMenuItem
            Dim ms(2) As MemoryStream

            mi(0) = New ApplicationMenuItem
            mi(0).Text = "RCMS Dialog"
            mi(0).Description = "Launch RCMS dialog to synchronize FP details between floor-plan and RCMS database"
            ms(0) = New MemoryStream
            My.Resources.cloudis32x32.Save(ms(0), System.Drawing.Imaging.ImageFormat.Gif)
            ms(0).Seek(0, SeekOrigin.Begin)
            mi(0).LargeImage = System.Windows.Media.Imaging.BitmapFrame.Create(ms(0))
            mi(0).CommandHandler = New AutoCADCommandHandler("CLDS_RCMS")
            menu.MenuContent.Items.Add(mi(0))

            mi(1) = New ApplicationMenuItem
            mi(1).Text = "Set PROJECTNAME"
            mi(1).Description = "Set drawing PROJECTNAME to allow connection to RCMS"
            ms(1) = New MemoryStream
            My.Resources._1403884245_Right.Save(ms(1), System.Drawing.Imaging.ImageFormat.Png)
            ms(1).Seek(0, SeekOrigin.Begin)
            mi(1).LargeImage = System.Windows.Media.Imaging.BitmapFrame.Create(ms(1))
            mi(1).CommandHandler = New AutoCADCommandHandler("CLDS_PROJECTNAMES" & Chr(10) & "PROJECTNAME")
            menu.MenuContent.Items.Add(mi(1))
        End If
    End Sub
#End Region
#Region "External functions"
#If CLDS_ACAD_V = "2010" Then
    Declare Auto Function acedPostCommand Lib "acad.exe" _
     Alias "?acedPostCommand@@YAHPB_W@Z" _
     (ByVal strExpr As String) As Integer
    Declare Auto Function acedPostCommand64 Lib "acad.exe" _
     Alias "?acedPostCommand@@YAHPEB_W@Z" _
     (ByVal strExpr As String) As Integer
#Else
    Declare Auto Function acedPostCommand Lib "accore.dll" _
     Alias "?acedPostCommand@@YAHPB_W@Z" _
     (ByVal strExpr As String) As Integer
    Declare Auto Function acedPostCommand64 Lib "accore.dll" _
     Alias "?acedPostCommand@@YAHPEB_W@Z" _
     (ByVal strExpr As String) As Integer
#End If
#End Region
#Region "V9 communications"
    Public Sub CLDS_InitialiseConnection()
        CMAPI = Nothing
    End Sub
    Public Function CLDS_URLConnection _
        (Optional ByVal p_init As Boolean = False) _
         As Boolean
        If p_init Then
            CLDS_InitialiseConnection()
        End If

        If CMAPI Is Nothing Then
            CMAPI = New Cloudis.XCMAPI_Client
        End If

        Dim nc As System.Net.NetworkCredential
        If (v_props.v_pruser = "" Or v_props.v_prpass = "") Then
            nc = Nothing
        Else
            nc = New System.Net.NetworkCredential(v_props.v_pruser, v_props.v_prpass)
        End If
        CMAPI.SessionID = ""
        'If Not (v_props.v_url = "" Or v_props.v_userid = "" Or v_props.v_passwd = "") Then
        If Not (v_props.v_url = "" Or v_props.v_userid = "") Then
            CMAPI.OpenSession(v_props.v_url, v_props.v_userid, v_props.v_passwd, "OPEN", nc)
        End If

        'If CMAPI.SessionID = "" Then
        'CMAPI.ShowConnect(v_props.v_url, v_props.v_userid, "OPEN", nc)
        'End If

        If CMAPI.SessionID = "" Then
            CLDS_DropConnection()
            CLDS_URLConnection = False
            Exit Function
        End If
        CMAPI.FormID = "V9RCMS"
        CMAPI.CMProjid = v_props.v_projid
        CMAPI.CMPOwner = v_props.v_powner
        CMAPI.CMApplicability = v_props.v_appl
        CMAPI.CMSource = v_props.v_source
        CMAPI.DebugURL = "N"
        CLDS_URLConnection = True
    End Function
    Public Sub CLDS_DropConnection()
        If Not CMAPI Is Nothing AndAlso CMAPI.SessionID <> "" Then
            Try
                CMAPI.CloseSession()
            Catch ex As Exception
            End Try
        End If
        CMAPI = Nothing
    End Sub
    Public Function CLDS_Query(ByVal ed As Editor, _
                               ByVal i As Integer, _
                               ByVal context As String, _
                               ByVal require As String, _
                               ByVal id As String, _
                               ByRef out(,) As String, _
                               ByRef cc As Collection, _
                               Optional ByVal vessel As Integer = 0) _
                               As Integer
        Dim r As String
        Dim nr As Integer, nc As Integer
        Dim ap As String
        If vessel = 0 Then
            ap = CMAPI.CMApplicability
        Else
            ap = Trim(Str$(Math.Pow(2, (vessel - 1))))
        End If
        CMERR = ""
        If i = 1 Then
            r = CMAPI.QueryCMPIC(ap, context, require, id, out, nr, nc)
        Else
            r = CMAPI.QueryCMPIC(ap, context, "-", "-", out, nr, nc)
        End If
        If Left$(r, 5) = "ERROR" Then
            If ed Is Nothing Then
                MsgBox(r, MsgBoxStyle.Critical, "RCMS")
            Else
                ed.WriteMessage(vbLf & "[" & context & "." & require & "] " & r & vbLf)
            End If
            CMERR = r
            CLDS_Query = -1
            Exit Function
        End If
        If nr = 0 Then
            CLDS_Query = 0
            Exit Function
        End If
        If out(0, 1) = "ERROR" Then
            If ed Is Nothing Then
                MsgBox(out(0, 1) & ":" & out(1, 1), MsgBoxStyle.Critical, "RCMS")
            Else
                ed.WriteMessage(vbLf & "[" & context & "." & require & "] " & out(0, 1) & ":" & out(1, 1))
            End If
            CMERR = out(0, 1) & ":" & out(1, 1)
            CLDS_Query = -1
            Exit Function
        End If
        If i = 1 Then
            cc = New Collection
            For j As Integer = 0 To nc - 1
                cc.Add(j, out(j, 0))
            Next
        End If
        CLDS_Query = nr
    End Function
#End Region
#Region "Project functions"
    Public Function CLDS_CheckCompatibility() As Boolean
        Dim rsno As Integer = Val(tokens("PD_RULESET"))
        Dim mindll As Integer = Val(tokens("PD_MINDLL"))
        If v_verno = rsno Then
            Return True
        End If
        If rsno > v_verno Then
            If v_verno >= mindll Then
                Return True
            Else
                MsgBox("Incompatible DLL and V9 versions" & Chr(10) & _
                        "V9 version:  " & Trim(Str$(rsno)) & Chr(10) & _
                        "DLL version: " & Trim(Str$(v_verno)) & _
                        ", need at least " & Trim(Str$(mindll)), _
                        MsgBoxStyle.Critical, "CMPIC V9 Compatibility Check")
            End If
        End If
        If v_verno > rsno Then
            If rsno >= v_minrs Then
                Return True
            Else
                MsgBox("Incompatible DLL and V9 versions" & Chr(10) & _
                        "DLL version: " & Trim(Str$(v_verno)) & Chr(10) & _
                        "V9 version:  " & Trim(Str$(rsno)) & _
                        ", need at least " & Trim(Str$(v_minrs)), _
                        MsgBoxStyle.Critical, "CMPIC V9 Compatibility Check")

            End If
        End If
        Return False
    End Function
    Public Sub CLDS_GetProjectDefaults()
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim sc(,) As String
        Dim scc As Collection = Nothing
        Dim id As String = ""
        If tokens Is Nothing Then
            tokens = New Collection
        End If
        tokens.Clear()
        Dim nr As Integer = CLDS_Query(ed, 1, "PR", "PD", id, sc, scc)
        If nr <= 0 Then
            Exit Sub
        End If
        If scc.Contains("PD_RULESET") Then
            tokens.Add(sc(scc("PD_RULESET"), 1), "PD_RULESET")
            tokens.Add(sc(scc("PD_MINDLL"), 1), "PD_MINDLL")
        Else
            tokens.Add("1309", "PD_RULESET")
            tokens.Add("1309", "PD_MINDLL")
        End If
        If CLDS_CheckCompatibility() Then
            pPrefs.x_v9st = tokens("PD_RULESET")
        Else
            tokens.Clear()
            Exit Sub
        End If
    End Sub
#End Region
#Region "Geometry"
    Public Function UCS2WCS(ByVal nTrans As Transaction, ByVal pUCS As Point3d) As Point3d
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim mUCS As Matrix3d = ed.CurrentUserCoordinateSystem
        Return pUCS.TransformBy(mUCS)
    End Function
    Public Function WCS2UCS(ByVal nTrans As Transaction, ByVal pWCS As Point3d) As Point3d
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim mWCS As Matrix3d = ed.CurrentUserCoordinateSystem.Inverse
        Return pWCS.TransformBy(mWCS)
    End Function
    Public Function CLDS_PointInZone(ByVal p_obj As ObjectId) As String
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim zone As String = ""
        Dim z_pt As Point3d = New Point3d(-10000, -10000, 0)
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using nTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim ps As PromptSelectionResult = CLDS_SelectZones(nTrans, ed)
                If ps Is Nothing Then
                    Return ""
                End If
                If ps.Value Is Nothing Then
                    Return ""
                End If
                Dim eB As BlockReference = TryCast(p_obj.GetObject(OpenMode.ForRead), BlockReference)
                If Not eB Is Nothing Then
                    Dim bt As BlockTable = DirectCast(nTrans.GetObject(doc.Database.BlockTableId, OpenMode.ForRead), BlockTable)
                    Dim btr As BlockTableRecord = DirectCast(nTrans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)
                    Dim ePt As Point3d = eB.Position
                    Dim lineE As Line = New Line(z_pt, ePt)
                    btr.AppendEntity(lineE)
                    nTrans.AddNewlyCreatedDBObject(lineE, True)
                    Dim d As Double = -1
                    For Each znO As ObjectId In ps.Value.GetObjectIds
                        Dim znB As BlockReference = TryCast(znO.GetObject(OpenMode.ForRead), BlockReference)
                        Dim ptC As Point3dCollection = New Point3dCollection()
                        ptC.Clear()
                        If Not znB Is Nothing Then
#If CLDS_ACAD_V = "2010" Then
                            lineE.IntersectWith(znB, Intersect.OnBothOperands, ptC, 0, 0)
#Else
                            Dim i1 As IntPtr = New IntPtr()
                            Dim i2 As IntPtr = New IntPtr()
                            lineE.IntersectWith(znB, Intersect.OnBothOperands, ptC, i1, i2)
#End If

                            If ptC.Count Mod 2 = 1 Then
                                For Each pt As Point3d In ptC
                                    Dim z As Double = pt.DistanceTo(ePt)
                                    If d < 0 Or z < d Then
                                        Dim zN As String = CLDS_GetBlockAttr(znB, pPrefs.t_zone)
                                        zone = zN
                                    End If
                                Next
                            End If
                        End If
                    Next
                    lineE.Erase()
                End If
                nTrans.Commit()
            End Using
        End Using
        Return zone
    End Function
#End Region
#Region "Block functions"
    Public Function CLDS_FindBlock(ByVal p_bt As BlockTable, _
                                  ByVal p_doc As Document, _
                                  ByVal p_name As String) _
                                  As ObjectId
        Dim nBlock As ObjectId
        If b_table Is Nothing Then
            b_table = New Collection
        End If
        If b_table.Contains(p_name) Then
            nBlock = b_table.Item(p_name)
            Return nBlock
        End If
        If Not p_bt.Has(p_name) Then
            Dim XFN As String = ""
            'Try
            'XFN = HostApplicationServices.Current.FindFile(p_name & ".dwg", p_doc.Database, FindFileHint.Default)
            'Catch ex As Autodesk.AutoCAD.Runtime.Exception
            'If ex.ErrorStatus = ErrorStatus.FilerError Then
            'XFN = ""
            'End If
            'End Try
            XFN = CLDS_Static_Utils.CLDS_FindFile(p_name & ".dwg")
            If XFN = "" Then
                p_doc.Editor.WriteMessage(vbLf & p_name & " block not found" & vbLf)
                nBlock = ObjectId.Null
            Else
                Dim xDB As Database = New Database(False, True)
                Try
                    xDB.ReadDwgFile(XFN, FileOpenMode.OpenForReadAndReadShare, True, "")
                    nBlock = p_doc.Database.Insert(p_name, xDB, True)
                Catch ex As Exception
                    p_doc.Editor.WriteMessage(vbLf & "Unable to load " & p_name & " block" & vbLf & ex.ToString)
                    nBlock = ObjectId.Null
                End Try
            End If
        Else
            nBlock = p_bt(p_name)
        End If
        If Not nBlock.IsNull Then
            b_table.Add(nBlock, p_name)
        End If
        CLDS_FindBlock = nBlock
    End Function
    Public Sub CLDS_CloneBlock(ByVal p_trans As Transaction, _
                          ByVal p_doc As Document, _
                          ByVal p_name As String, _
                          ByVal p_old As ObjectId, _
                          ByVal p_new As BlockReference)
        Dim btrec As BlockTableRecord = DirectCast(p_trans.GetObject(p_old, OpenMode.ForRead), BlockTableRecord)
        If String.IsNullOrEmpty(btrec.Name) Then
            btrec.UpgradeOpen()
            btrec.Name = p_name
            btrec.DowngradeOpen()
        End If
        If btrec.HasAttributeDefinitions Then
            For Each aoid As ObjectId In btrec
                Dim ent As Entity = DirectCast(aoid.GetObject(OpenMode.ForRead), Entity)
                Dim ad As AttributeDefinition = TryCast(ent, AttributeDefinition)
                If ad IsNot Nothing Then
                    Dim ar As AttributeReference = New AttributeReference()
                    ar.SetPropertiesFrom(ad)
                    ar.Visible = ad.Visible
                    ar.SetAttributeFromBlock(ad, p_new.BlockTransform)
                    ar.HorizontalMode = ad.HorizontalMode
                    ar.VerticalMode = ad.VerticalMode
                    ar.Rotation = ad.Rotation
                    ar.Tag = ad.Tag
                    ar.FieldLength = ad.FieldLength
                    ar.TextString = ad.TextString
                    ar.AdjustAlignment(p_doc.Database)
                    p_new.AttributeCollection.AppendAttribute(ar)
                    p_trans.AddNewlyCreatedDBObject(ar, True)
                End If
            Next
        End If

    End Sub
    Public Sub CLDS_SetBlockAttr(ByVal p_br As BlockReference, _
                                 ByVal p_tag As String, _
                                 ByVal p_value As String)
        Dim v As String
        If String.IsNullOrEmpty(p_value) Then
            v = ""
        Else
            v = p_value
        End If
        For Each aoid As ObjectId In p_br.AttributeCollection
            Dim ar As AttributeReference = DirectCast(aoid.GetObject(OpenMode.ForRead), AttributeReference)
            If ar.Tag = p_tag Then
                ar.UpgradeOpen()
                ar.TextString = v
                Exit For
            End If
        Next
    End Sub
    Public Function CLDS_GetBlockAttr(ByVal p_br As BlockReference, _
                                     ByVal p_tag As String) _
                                     As String
        CLDS_GetBlockAttr = ""
        For Each aID As ObjectId In p_br.AttributeCollection
            Dim a As AttributeReference = DirectCast(aID.GetObject(OpenMode.ForRead), AttributeReference)
            If a.Tag = p_tag Then
                If String.IsNullOrEmpty(a.TextString) Then
                    CLDS_GetBlockAttr = ""
                Else
                    CLDS_GetBlockAttr = a.TextString
                End If
                Exit Function
            End If
        Next
    End Function
    Public Function CLDS_PointWP(ByVal p_dialog As RCMS_Container) As ObjectId
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim br As BlockReference = Nothing
        Dim npo As PromptPointOptions
        npo = New PromptPointOptions("Select WP insertion point")
        Dim npr As PromptPointResult = Nothing
        'Using ed.StartUserInteraction(p_dialog)
        'p_dialog.Hide()
        'CancelPrior()
        npr = ed.GetPoint(npo)
        CLDS_Static_Utils.CLDS_WriteMessage(ed, " ")
        'p_dialog.Show()
        'End Using
        If npr.Status = PromptStatus.OK Then
            Using acLckDoc As DocumentLock = doc.LockDocument()
                Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                    Dim xp As Point3d = npr.Value
                    Dim np As Point3d = WCS2UCS(dTrans, xp)
                    Dim bt As BlockTable = DirectCast(dTrans.GetObject(doc.Database.BlockTableId, OpenMode.ForRead), BlockTable)
                    Dim btr As BlockTableRecord = DirectCast(dTrans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)
                    Dim nBlock As ObjectId = CLDS_FindBlock(bt, doc, pPrefs.b_wp)
                    If nBlock.IsNull Then
                        'CLDS_Static_Utils.CLDS_WriteMessage(ed, "ERROR: Unable to locate WP block " & pPrefs.b_wp & " for insertion")
                        MsgBox("ERROR: Unable to locate WP block " & pPrefs.b_wp & " for insertion", MsgBoxStyle.Critical, "RCMS AutoCAD")
                    Else
                        br = New BlockReference(np, nBlock)
                        CLDS_CheckLayer(dTrans, doc, pPrefs.l_wp, pPrefs.c_wp)
                        br.Layer = pPrefs.l_wp
                        br.TransformBy(Matrix3d.Scaling(pPrefs.f_wp, np))
                        btr.UpgradeOpen()
                        btr.AppendEntity(br)
                        dTrans.AddNewlyCreatedDBObject(br, True)
                        CLDS_CloneBlock(dTrans, doc, pPrefs.b_wp, nBlock, br)
                    End If
                    dTrans.Commit()
                End Using
            End Using
            If br Is Nothing Then
                Return ObjectId.Null
            Else
                Return br.ObjectId
            End If
        Else
            Return ObjectId.Null
        End If
    End Function
    Public Sub CLDS_PointZone(ByVal p_dialog As RCMS_Container)
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim br As BlockReference = Nothing
        Dim npo As PromptPointOptions
        npo = New PromptPointOptions("Select zone insertion point")
        Dim npr As PromptPointResult = Nothing
        'Using ed.StartUserInteraction(p_dialog)
        'p_dialog.Hide()
        'CancelPrior()
        npr = ed.GetPoint(npo)
        CLDS_Static_Utils.CLDS_WriteMessage(ed, " ")
        'p_dialog.Show()
        'End Using
        If npr.Status = PromptStatus.OK Then
            Dim spo As New PromptStringOptions("Enter zone name e.g. ZONE-1: ")
            Dim spr As PromptResult = Nothing
            spr = ed.GetString(spo)
            If spr.Status = PromptStatus.OK Then
                Using acLckDoc As DocumentLock = doc.LockDocument()
                    Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                        Dim xp As Point3d = npr.Value
                        Dim np As Point3d = WCS2UCS(dTrans, xp)
                        Dim bt As BlockTable = DirectCast(dTrans.GetObject(doc.Database.BlockTableId, OpenMode.ForRead), BlockTable)
                        Dim btr As BlockTableRecord = DirectCast(dTrans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)
                        Dim nBlock As ObjectId = CLDS_FindBlock(bt, doc, pPrefs.b_zone)
                        If nBlock.IsNull Then
                            MsgBox("ERROR: Unable to locate zone block " & pPrefs.b_zone & " for insertion", MsgBoxStyle.Critical, "RCMS AutoCAD")
                            ' CLDS_Static_Utils.CLDS_WriteMessage(ed, "ERROR: Unable to locate zone block " & pPrefs.b_zone & " for insertion")
                        Else
                            br = New BlockReference(np, nBlock)
                            CLDS_CheckLayer(dTrans, doc, pPrefs.l_zone, pPrefs.c_zone)
                            br.Layer = pPrefs.l_zone
                            br.TransformBy(Matrix3d.Scaling(pPrefs.f_zone, np))
                            btr.UpgradeOpen()
                            btr.AppendEntity(br)
                            dTrans.AddNewlyCreatedDBObject(br, True)
                            CLDS_CloneBlock(dTrans, doc, pPrefs.b_zone, nBlock, br)
                        End If
                        If Not br Is Nothing Then
                            Dim zoneid As String = spr.StringResult.ToUpper
                            CLDS_SetBlockAttr(br, pPrefs.t_zone, zoneid)
                        End If
                        dTrans.Commit()
                    End Using
                End Using
                If Not br Is Nothing Then
                    CLDS_SelectObject(br.ObjectId)
                End If
            End If
        End If
    End Sub
#End Region
#Region "Layer functions"
    Public Sub CLDS_DeleteLayer(ByVal p_trans As Transaction, _
                               ByVal p_doc As Document, _
                               ByVal p_layer As String)
        Dim lt As LayerTable = DirectCast(p_trans.GetObject(p_doc.Database.LayerTableId, OpenMode.ForRead), LayerTable)
        If lt.Has(p_layer) Then
            Dim ltr As LayerTableRecord = DirectCast(p_trans.GetObject(lt.Item(p_layer), OpenMode.ForWrite), LayerTableRecord)
            ltr.Erase()
        End If
    End Sub
    Public Sub CLDS_CheckLayer(ByVal p_trans As Transaction, _
                               ByVal p_doc As Document, _
                               ByVal p_layer As String, _
                               ByVal p_colour As Autodesk.AutoCAD.Colors.Color, _
                               Optional ByVal p_hide As Boolean = False)
        Dim lt As LayerTable = DirectCast(p_trans.GetObject(p_doc.Database.LayerTableId, OpenMode.ForRead), LayerTable)
        If Not lt.Has(p_layer) Then
            Dim ltr As LayerTableRecord = New LayerTableRecord()
            ltr.Name = p_layer
            ltr.Color = p_colour
            ltr.IsOff = p_hide
            lt.UpgradeOpen()
            Dim nLayer As ObjectId = lt.Add(ltr)
            lt.DowngradeOpen()
            p_trans.AddNewlyCreatedDBObject(ltr, True)
            Dim lft As LayerFilterTree = nLayer.Database.LayerFilters
            Dim lfc As LayerFilterCollection = lft.Root.NestedFilters
            Dim lg As LayerGroup = Nothing
            For Each xlg As LayerFilter In lfc
                If xlg.Name = pPrefs.g_clds Then
                    lg = xlg
                    Exit For
                End If
            Next
            If lg Is Nothing Then
                lg = New LayerGroup
                lg.Name = pPrefs.g_clds
                lg.LayerIds.Add(nLayer)
                lfc.Add(lg)
                nLayer.Database.LayerFilters = lft
            Else
                lg.LayerIds.Add(nLayer)
                nLayer.Database.LayerFilters = lft
            End If
        Else
            Dim xtr As LayerTableRecord = DirectCast(p_trans.GetObject(lt(p_layer), OpenMode.ForRead), LayerTableRecord)
            If Not xtr.Color.Equals(p_colour) Then
                xtr.UpgradeOpen()
                xtr.Color = p_colour
                xtr.DowngradeOpen()
            End If
        End If

    End Sub
    Public Sub CLDS_CheckLayer(ByVal p_trans As Transaction, _
                            ByVal p_doc As Document, _
                            ByVal p_layer As String, _
                            Optional ByVal p_red As Byte = 255, _
                            Optional ByVal p_green As Byte = 255, _
                            Optional ByVal p_blue As Byte = 255, _
                            Optional ByVal p_hide As Boolean = False)
        Dim c As Autodesk.AutoCAD.Colors.Color = Autodesk.AutoCAD.Colors.Color.FromRgb(p_red, p_green, p_blue)
        CLDS_CheckLayer(p_trans, p_doc, p_layer, c, p_hide)
    End Sub
    Public Sub CLDS_CheckLayer(ByVal p_trans As Transaction, _
                            ByVal p_doc As Document, _
                            ByVal p_layer As String, _
                            ByVal p_scolour As System.Drawing.Color, _
                            Optional ByVal p_hide As Boolean = False)
        Dim c As Autodesk.AutoCAD.Colors.Color = Autodesk.AutoCAD.Colors.Color.FromColor(p_scolour)
        CLDS_CheckLayer(p_trans, p_doc, p_layer, c, p_hide)
    End Sub
    Public Sub CLDS_ColourLayer(ByVal p_trans As Transaction, ByVal p_doc As Document, ByVal p_layer As String, ByVal p_scolour As System.Drawing.Color)
        Dim lt As LayerTable = DirectCast(p_trans.GetObject(p_doc.Database.LayerTableId, OpenMode.ForRead), LayerTable)
        If lt.Has(p_layer) Then
            Dim xtr As LayerTableRecord = DirectCast(p_trans.GetObject(lt(p_layer), OpenMode.ForRead), LayerTableRecord)
            Dim c As Autodesk.AutoCAD.Colors.Color = Autodesk.AutoCAD.Colors.Color.FromColor(p_scolour)
            If Not xtr.Color.Equals(c) Then
                xtr.UpgradeOpen()
                xtr.Color = c
                xtr.DowngradeOpen()
            End If
        End If
    End Sub
    Public Sub CLDS_ColourLayerByPrefs()
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using lTrans As Transaction = doc.TransactionManager.StartTransaction
                CLDS_ColourLayer(lTrans, doc, pPrefs.l_wp, pPrefs.c_wp)
                CLDS_ColourLayer(lTrans, doc, pPrefs.l_zone, pPrefs.c_zone)
                lTrans.Commit()
            End Using
        End Using
    End Sub
    Public Function CLDS_ErrorLayer(ByVal p_main As String, ByVal p_mssg As String, Optional ByVal p_action As String = "") As String
        CLDS_ErrorLayer = p_main
        Dim l As Integer, r As Integer
        l = InStr(p_mssg, "[")
        If l = 0 Then
            Exit Function
        End If
        r = InStr(p_mssg, "]")
        If r < l Then
            Exit Function
        End If
        Dim n As String = Mid(p_mssg, l + 1, r - l - 1)
        If p_action = "" Then
            CLDS_ErrorLayer = p_main & "_" & n
        Else
            CLDS_ErrorLayer = p_main & "_" & p_action & "_" & n
        End If
    End Function
#End Region
#Region "XRecord functions"
    Public Function CLDS_GetXRecord(ByVal dTrans As Transaction, ByVal dObj As DBObject) As ResultBuffer
        Try
            Dim xDict As DBDictionary = DirectCast(dTrans.GetObject(dObj.ExtensionDictionary, OpenMode.ForRead), DBDictionary)
            Dim xr As Xrecord = TryCast(dTrans.GetObject(xDict.GetAt(pPrefs.d_xrec), OpenMode.ForRead), Xrecord)
            If xr Is Nothing Then
                CLDS_GetXRecord = Nothing
            Else
                CLDS_GetXRecord = xr.Data
            End If
        Catch ex As Exception
            CLDS_GetXRecord = Nothing
        End Try
    End Function
    Public Sub CLDS_SetGridXRec(ByVal dTrans As Transaction, ByVal tableE As Table, ByVal tag As String)
        If tableE.ExtensionDictionary = ObjectId.Null Then
            tableE.CreateExtensionDictionary()
        End If
        Dim lDict As DBDictionary = DirectCast(dTrans.GetObject(tableE.ExtensionDictionary, OpenMode.ForWrite), DBDictionary)
        Dim lxrec As Xrecord = New Xrecord()
        Dim lxbuf As ResultBuffer = New ResultBuffer()
        lxbuf.Add(New TypedValue(DxfCode.Text, tag))
        lxrec.Data = lxbuf
        lDict.SetAt(pPrefs.d_xrec, lxrec)
        dTrans.AddNewlyCreatedDBObject(lxrec, True)
    End Sub
    Public Sub CLDS_SetFPXRec(ByVal dTrans As Transaction, ByVal wpE As BlockReference, ByVal p_projid As String, ByVal p_phase As String)
        If wpE Is Nothing Then
            Exit Sub
        End If
        If wpE.ExtensionDictionary = ObjectId.Null Then
            wpE.CreateExtensionDictionary()
        End If
        Dim lDict As DBDictionary = DirectCast(dTrans.GetObject(wpE.ExtensionDictionary, OpenMode.ForWrite), DBDictionary)
        Dim lxrec As Xrecord = New Xrecord()
        Dim lxbuf As ResultBuffer = New ResultBuffer()
        lxbuf.Add(New TypedValue(DxfCode.Text, p_projid))
        lxbuf.Add(New TypedValue(DxfCode.Text, p_phase))
        lxrec.Data = lxbuf
        lDict.SetAt(pPrefs.d_xrec, lxrec)
        dTrans.AddNewlyCreatedDBObject(lxrec, True)
    End Sub
    Public Sub CLDS_RegisterAppName(ByVal dTrans As Transaction)
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim db As Database = doc.Database
        Dim rt As RegAppTable = DirectCast(dTrans.GetObject(db.RegAppTableId, OpenMode.ForRead, False), RegAppTable)
        If Not (rt.Has(pPrefs.d_xrec)) Then
            rt.UpgradeOpen()
            Dim rtr As RegAppTableRecord = New RegAppTableRecord
            rtr.Name = pPrefs.d_xrec
            rt.Add(rtr)
            dTrans.AddNewlyCreatedDBObject(rtr, True)
        End If
    End Sub
    Public Sub CLDS_SetGridXData(ByVal dTrans As Transaction, ByVal tableE As Table, ByVal tag As String)
        CLDS_RegisterAppName(dTrans)
        Dim rb As ResultBuffer = New ResultBuffer()
        rb.Add(New TypedValue(DxfCode.ExtendedDataRegAppName, pPrefs.d_xrec))
        rb.Add(New TypedValue(1000, tag))
        tableE.XData = rb
        rb.Dispose()
    End Sub
#End Region
#Region "Entity highlight/selection"
    Public Sub CancelPrior()
        Dim ok As Boolean = True
        Try
            Dim i As Integer = acedPostCommand("CANCELCMD")
        Catch e As System.EntryPointNotFoundException
            ok = False
        End Try
        If ok Then
            Exit Sub
        End If
        Try
            Dim i As Integer = acedPostCommand64("CANCELCMD")
        Catch e As System.EntryPointNotFoundException
            ok = False
        End Try
    End Sub
    Private Shared Function CLDS_CreateFilterListForBlocks(ByVal blkNames As List(Of String)) As TypedValue()
        ' If we don't have any block names, return null

        If blkNames.Count = 0 Then
            Return Nothing
        End If

        ' If we only have one, return an array of a single value

        If blkNames.Count = 1 Then
            Return New TypedValue() {New TypedValue(CInt(DxfCode.BlockName), blkNames(0))}
        End If

        ' We have more than one block names to search for...

        ' Create a list big enough for our block names plus
        ' the containing "or" operators

        Dim tvl As New List(Of TypedValue)(blkNames.Count + 2)

        ' Add the initial operator

        tvl.Add(New TypedValue(CInt(DxfCode.[Operator]), "<or"))

        ' Add an entry for each block name, prefixing the
        ' anonymous block names with a reverse apostrophe

        For Each blkName As String In blkNames
            tvl.Add(New TypedValue(CInt(DxfCode.BlockName), (If(blkName.StartsWith("*"), "`" & blkName, blkName))))
        Next

        ' Add the final operator

        tvl.Add(New TypedValue(CInt(DxfCode.[Operator]), "or>"))

        ' Return an array from the list

        Return tvl.ToArray()
    End Function

    Public Shared Function CLDS_SelectDynamicBlocksList(ByVal p_trans As Transaction, ByVal p_ed As Editor, ByVal p_names As List(Of String)) As PromptSelectionResult
        Dim doc As Document = p_ed.Document
        Dim blkNames As New List(Of String)()
        For Each blkName As String In p_names
            blkNames.Add(blkName)

            Dim bt = DirectCast(p_trans.GetObject(doc.Database.BlockTableId, OpenMode.ForRead), BlockTable)

            ' Start by getting access to our block, if it exists

            If Not bt.Has(blkName) Then
                'p_ed.WriteMessage(vbLf & "Cannot find block called ""{0}"".", blkName)
                Continue For
            End If

            ' Get the anonymous block names
            Dim btr = DirectCast(p_trans.GetObject(bt(blkName), OpenMode.ForRead), BlockTableRecord)

            If Not btr.IsDynamicBlock Then
                'p_ed.WriteMessage(vbLf & "Cannot find a dynamic block called ""{0}"".", blkName)
                Continue For
            End If

            ' Get the anonymous blocks and add them to our list

            Dim anonBlks = btr.GetAnonymousBlockIds()
            For Each bid As ObjectId In anonBlks
                Dim btr2 = DirectCast(p_trans.GetObject(bid, OpenMode.ForRead), BlockTableRecord)

                blkNames.Add(btr2.Name)
            Next
        Next

        'If blkNames.Count = 0 Then
        'Return Nothing
        'End If

        Dim sf As New SelectionFilter(CLDS_CreateFilterListForBlocks(blkNames))
        Dim psr As PromptSelectionResult = p_ed.SelectAll(sf)

        'p_ed.WriteMessage(vbLf & "Found {0} entit{1}.", psr.Value.Count, (If(psr.Value.Count = 1, "y", "ies")))
        Return psr
    End Function
    Public Shared Function CLDS_SelectDynamicBlocks(ByVal p_trans As Transaction, ByVal p_ed As Editor, ByVal p_name As String) As PromptSelectionResult
        Dim blkNames As New List(Of String)()
        blkNames.Add(p_name)
        Return CLDS_SelectDynamicBlocksList(p_trans, p_ed, blkNames)
    End Function
    Public Function CLDS_FilterWPs() As SelectionFilter
        Dim bn As String = pPrefs.b_wp & "," & pPrefs.b_wpb & "," & pPrefs.b_wpl & "," & pPrefs.b_wpr & "," & pPrefs.b_wpt & "," & pPrefs.b_wpd
        Dim ntvs() As TypedValue = New TypedValue() _
            {New TypedValue(DxfCode.Start, "INSERT"), _
            New TypedValue(DxfCode.BlockName, bn)}
        Dim nsf As SelectionFilter = New SelectionFilter(ntvs)
        Return nsf
    End Function
    Public Function CLDS_SelectWPs(ByVal p_trans As Transaction, ByVal p_ed As Editor) As PromptSelectionResult
        'Dim nsf As SelectionFilter = CLDS_FilterWPs()
        'Return p_ed.SelectAll(nsf)
        Dim blkNames As New List(Of String)()
        blkNames.Add(pPrefs.b_wp)
        blkNames.Add(pPrefs.b_wpb)
        blkNames.Add(pPrefs.b_wpl)
        blkNames.Add(pPrefs.b_wpr)
        blkNames.Add(pPrefs.b_wpt)
        blkNames.Add(pPrefs.b_wpd)
        Return CLDS_SelectDynamicBlocksList(p_trans, p_ed, blkNames)
    End Function
    Public Function CLDS_FilterZones() As SelectionFilter
        Dim ntvs() As TypedValue = New TypedValue() _
            {New TypedValue(DxfCode.Start, "INSERT"), _
            New TypedValue(DxfCode.BlockName, pPrefs.b_zone)}
        Dim nsf As SelectionFilter = New SelectionFilter(ntvs)
        Return nsf
    End Function
    Public Function CLDS_SelectZones(ByVal p_trans As Transaction, ByVal p_ed As Editor) As PromptSelectionResult
        '        Dim nsf As SelectionFilter = CLDS_FilterZones()
        '        Return p_ed.SelectAll(nsf)
        Return CLDS_SelectDynamicBlocks(p_trans, p_ed, pPrefs.b_zone)
    End Function
    Public Function CLDS_FilterTables() As SelectionFilter
        Dim ntvs() As TypedValue = New TypedValue() _
            {New TypedValue(DxfCode.Operator, "<and"), _
                New TypedValue(DxfCode.ExtendedDataRegAppName, pPrefs.d_xrec), _
                New TypedValue(DxfCode.LayerName, pPrefs.l_grid), _
            New TypedValue(DxfCode.Operator, "and>")}
        Dim nsf As SelectionFilter = New SelectionFilter(ntvs)
        Return nsf
    End Function
    Public Function CLDS_SelectTables(ByVal p_trans As Transaction, ByVal p_ed As Editor) As PromptSelectionResult
        Dim nsf As SelectionFilter = CLDS_FilterTables()
        Return p_ed.SelectAll(nsf)
    End Function
    Public Function CLDS_IsWP(ByVal p_obj As ObjectId, Optional ByVal p_id As String = "", Optional ByVal p_excl As BlockReference = Nothing) As BlockReference
        Dim cn As String = UCase(p_obj.ObjectClass.Name)
        If cn = "ACDBBLOCKREFERENCE" Then
            Dim wpB As BlockReference
            Dim dID As String
            wpB = DirectCast(p_obj.GetObject(OpenMode.ForRead), BlockReference)
            Dim wpN As String = wpB.Name
            If wpB.IsDynamicBlock Then
                Dim wpD As BlockTableRecord = DirectCast(wpB.DynamicBlockTableRecord.GetObject(OpenMode.ForRead, False), BlockTableRecord)
                wpN = wpD.Name
            End If
            dID = CLDS_GetBlockAttr(wpB, pPrefs.t_fpid)
            If (wpN <> pPrefs.b_wp And wpN <> pPrefs.b_wpb And wpN <> pPrefs.b_wpl And wpN <> pPrefs.b_wpr And wpN <> pPrefs.b_wpt And wpN <> pPrefs.b_wpd) Or dID = "" Then
                Return Nothing
            Else
                If p_id = "" Then
                    Return wpB
                Else
                    If Not p_excl Is Nothing AndAlso wpB = p_excl Then
                        Return Nothing
                    End If
                    If p_id = dID Then
                        Return wpB
                    Else
                        Return Nothing
                    End If
                End If
            End If
        Else
            Return Nothing
        End If
    End Function
    Public Sub CLDS_PickWP(ByRef o_fpid As String)
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        o_fpid = ""
        Dim slObj As ObjectId = ObjectId.Null
        Try
            Dim psr As PromptSelectionResult = ed.SelectImplied
            If psr.Status = PromptStatus.OK Then
                Dim sobj() As ObjectId = psr.Value.GetObjectIds
                If sobj.GetLength(0) = 1 Then
                    slObj = sobj(0)
                Else
                    ed.WriteMessage(vbCrLf & "Too many entities selected")
                End If
                Dim nobj() As ObjectId
                ed.SetImpliedSelection(nobj)
            End If
        Catch ex As Exception

        End Try
        If slObj.IsNull Then
            Dim peo As New PromptEntityOptions(vbLf & "Select WP block:")
            peo.SetRejectMessage("WP block selection required." & vbCrLf)
            peo.AddAllowedClass(GetType(Autodesk.AutoCAD.DatabaseServices.BlockReference), False)
            Dim per As PromptEntityResult = ed.GetEntity(peo)
            If per.Status = PromptStatus.OK Then
                slObj = per.ObjectId
            Else
                CLDS_Static_Utils.CLDS_WriteMessage(ed, "Selection cancelled")
                Exit Sub
            End If
        End If
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using nTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim cn As String = UCase(slObj.ObjectClass.Name)
                If cn = "ACDBBLOCKREFERENCE" Then
                    Dim wpB As BlockReference = DirectCast(slObj.GetObject(OpenMode.ForRead), BlockReference)
                    Dim wpN As String = wpB.Name
                    If wpB.IsDynamicBlock Then
                        Dim wpD As BlockReference = DirectCast(wpB.DynamicBlockTableRecord.GetObject(OpenMode.ForRead, False), BlockReference)
                        wpN = wpD.Name
                    End If
                    Dim dID As String = CLDS_GetBlockAttr(wpB, pPrefs.t_fpid)
                    If (wpN <> pPrefs.b_wp And wpN <> pPrefs.b_wpb And wpN <> pPrefs.b_wpl And wpN <> pPrefs.b_wpr And wpN <> pPrefs.b_wpt And wpN <> pPrefs.b_wpd) Or dID = "" Then
                        CLDS_Static_Utils.CLDS_WriteMessage(ed, "Selected block is not a WP")
                        Exit Sub
                    Else
                        o_fpid = dID
                        CLDS_Static_Utils.CLDS_WriteMessage(ed, "WP " & o_fpid)
                    End If
                Else
                    CLDS_Static_Utils.CLDS_WriteMessage(ed, "Invalid selection")
                End If
                nTrans.Commit()
            End Using
        End Using
    End Sub
    Public Function CLDS_PickWPBlock() As BlockReference
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim o_fpid As String
        Dim slObj As ObjectId = ObjectId.Null
        CLDS_PickWPBlock = Nothing
        Try
            Dim psr As PromptSelectionResult = ed.SelectImplied
            If psr.Status = PromptStatus.OK Then
                Dim sobj() As ObjectId = psr.Value.GetObjectIds
                If sobj.GetLength(0) = 1 Then
                    slObj = sobj(0)
                Else
                    ed.WriteMessage(vbCrLf & "Too many entities selected")
                End If
                Dim nobj() As ObjectId
                ed.SetImpliedSelection(nobj)
            End If
        Catch ex As Exception

        End Try
        If slObj.IsNull Then
            Dim peo As New PromptEntityOptions(vbLf & "Select WP block:")
            peo.SetRejectMessage("WP block selection required." & vbCrLf)
            peo.AddAllowedClass(GetType(Autodesk.AutoCAD.DatabaseServices.BlockReference), False)
            Dim per As PromptEntityResult = ed.GetEntity(peo)
            If per.Status = PromptStatus.OK Then
                slObj = per.ObjectId
            Else
                CLDS_Static_Utils.CLDS_WriteMessage(ed, "Selection cancelled")
                Exit Function
            End If
        End If
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using nTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim cn As String = UCase(slObj.ObjectClass.Name)
                If cn = "ACDBBLOCKREFERENCE" Then
                    Dim wpB As BlockReference = DirectCast(slObj.GetObject(OpenMode.ForRead), BlockReference)
                    Dim wpN As String = wpB.Name
                    If wpB.IsDynamicBlock Then
                        Dim wpD As BlockReference = DirectCast(wpB.DynamicBlockTableRecord.GetObject(OpenMode.ForRead, False), BlockReference)
                        wpN = wpD.Name
                    End If
                    Dim dID As String = CLDS_GetBlockAttr(wpB, pPrefs.t_fpid)
                    If (wpN <> pPrefs.b_wp And wpN <> pPrefs.b_wpb And wpN <> pPrefs.b_wpl And wpN <> pPrefs.b_wpr And wpN <> pPrefs.b_wpt And wpN <> pPrefs.b_wpd) Or dID = "" Then
                        CLDS_Static_Utils.CLDS_WriteMessage(ed, "Selected block is not a WP")
                        Exit Function
                    Else
                        o_fpid = dID
                        CLDS_Static_Utils.CLDS_WriteMessage(ed, "WP " & o_fpid)
                        CLDS_PickWPBlock = wpB
                    End If
                Else
                    CLDS_Static_Utils.CLDS_WriteMessage(ed, "Invalid selection")
                End If
                nTrans.Commit()
            End Using
        End Using
    End Function
    Public Function CLDS_FindWP(ByVal p_trans As Transaction, ByVal p_wp As String, Optional ByVal p_psr As PromptSelectionResult = Nothing, Optional ByVal p_excl As BlockReference = Nothing) As ObjectId
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim ps As PromptSelectionResult
        If p_psr Is Nothing Then
            ps = CLDS_SelectWPs(p_trans, ed)
        Else
            ps = p_psr
        End If
        If ps.Status <> PromptStatus.OK Then
            Return ObjectId.Null
        End If
        If ps.Value Is Nothing Then
            Return ObjectId.Null
        End If
        For Each wpO As ObjectId In ps.Value.GetObjectIds
            Dim wpB As BlockReference = CLDS_IsWP(wpO, p_wp, p_excl)
            If Not wpB Is Nothing Then
                Return wpO
            End If
        Next
        Return ObjectId.Null
    End Function
    Public Function CLDS_WP_Has_Cable(ByVal p_trans As Transaction, ByVal p_wp As BlockReference, ByVal p_cabid As String) As Boolean
        For i = 1 To pPrefs.x_cbno
            Dim n As String = Trim(Str$(i))
            Dim c As String = CLDS_GetBlockAttr(p_wp, pPrefs.t_cbid & n)
            If c = p_cabid Then
                Return True
            End If
        Next
        Return False
    End Function
    Public Sub CLDS_FindAllWP(ByVal p_trans As Transaction, ByVal p_wp As String, ByVal p_psr As PromptSelectionResult, ByRef p_excl As List(Of ObjectId), Optional ByVal p_cabid As String = "")
        If p_psr.Status <> PromptStatus.OK Then
            Exit Sub
        End If
        If p_psr.Value Is Nothing Then
            Exit Sub
        End If
        For Each wpO As ObjectId In p_psr.Value.GetObjectIds
            Dim wpB As BlockReference
            wpB = CLDS_IsWP(wpO, p_wp)
            Dim wpF As Boolean = False
            If Not wpB Is Nothing Then
                Debug.Print("Found WP " & p_wp)
                Dim f As Boolean = True
                If p_cabid <> "" Then
                    f = CLDS_WP_Has_Cable(p_trans, wpB, p_cabid)
                End If
                If f Then
                    For Each xpO As ObjectId In p_excl
                        If wpO.Equals(xpO) Then
                            wpF = True
                            Exit For
                        End If
                    Next
                    If Not wpF Then
                        p_excl.Add(wpO)
                        Debug.Print("Add " & p_wp & " to list")
                    End If
                End If
            End If
        Next
    End Sub
    Public Function CLDS_SingleWP() As BlockReference
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim slObj As ObjectId = ObjectId.Null
        Try
            Dim psr As PromptSelectionResult = ed.SelectImplied
            If psr.Status = PromptStatus.OK Then
                Dim sobj() As ObjectId = psr.Value.GetObjectIds
                If sobj.GetLength(0) = 1 Then
                    slObj = sobj(0)
                End If
            End If
        Catch ex As Exception

        End Try
        If slObj.IsNull Then
            Return Nothing
        End If
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using nTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim cn As String = UCase(slObj.ObjectClass.Name)
                If cn = "ACDBBLOCKREFERENCE" Then
                    Dim wpB As BlockReference = DirectCast(slObj.GetObject(OpenMode.ForRead), BlockReference)
                    Dim wpN As String = wpB.Name
                    If wpB.IsDynamicBlock Then
                        Dim wpD As BlockTableRecord = DirectCast(wpB.DynamicBlockTableRecord.GetObject(OpenMode.ForRead, False), BlockTableRecord)
                        wpN = wpD.Name
                    End If
                    Dim dID As String = CLDS_GetBlockAttr(wpB, pPrefs.t_fpid)
                    If (wpN <> pPrefs.b_wp And wpN <> pPrefs.b_wpb And wpN <> pPrefs.b_wpl And wpN <> pPrefs.b_wpr And wpN <> pPrefs.b_wpt And wpN <> pPrefs.b_wpd) Or dID = "" Then
                        Return Nothing
                    Else
                        Return wpB
                    End If
                End If
                nTrans.Commit()
            End Using
        End Using
        Return Nothing
    End Function
    Public Sub CLDS_SelectObject(ByVal p_obj As ObjectId, Optional ByVal p_zoom As Boolean = False)
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim zobj() As ObjectId
        ed.SetImpliedSelection(zobj)
        If p_obj.IsNull Then
            Exit Sub
        End If
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim xobj As ObjectId()
                xobj = New ObjectId() {p_obj}
                ed.SetImpliedSelection(xobj)
                If p_zoom Then
                    If Not p_obj.IsNull Then
                        CLDS_Static_Utils.ZoomToObject(dTrans, p_obj)
                    End If
                End If
                dTrans.Commit()
            End Using
        End Using
        Autodesk.AutoCAD.ApplicationServices.Application.UpdateScreen()
    End Sub
    Public Sub CLDS_SelectWP(ByVal p_id As String, Optional ByVal p_zoom As Boolean = False, Optional ByVal p_excl As BlockReference = Nothing)
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim zobj() As ObjectId
        ed.SetImpliedSelection(zobj)
        If p_id = "" Then
            Exit Sub
        End If
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim nObj As ObjectId
                Dim xobj As ObjectId()
                nObj = CLDS_FindWP(dTrans, p_id, Nothing, p_excl)
                If Not nObj.IsNull Then
                    xobj = New ObjectId() {nObj}
                    ed.SetImpliedSelection(xobj)
                End If
                If p_zoom Then
                    If Not nObj.IsNull Then
                        CLDS_Static_Utils.ZoomToObject(dTrans, nObj)
                    End If
                End If
                dTrans.Commit()
            End Using
        End Using
        Autodesk.AutoCAD.ApplicationServices.Application.UpdateScreen()
    End Sub
    Public Sub CLDS_SelectWPsByLVFP(ByVal p_lv As System.Windows.Forms.ListView, ByRef wpL As List(Of ObjectId))
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim zobj() As ObjectId
        Try
            ed.SetImpliedSelection(zobj)
        Catch ex As Exception
        End Try
        wpL.Clear()
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim psr As PromptSelectionResult = CLDS_SelectWPs(dTrans, ed)
                If psr.Status = PromptStatus.OK Then
                    For Each lvi As System.Windows.Forms.ListViewItem In p_lv.SelectedItems
                        Debug.Print("Look for FP " & lvi.Text)
                        CLDS_FindAllWP(dTrans, lvi.Text, psr, wpL)
                        Debug.Print("FP list size " & Str$(wpL.Count))
                    Next
                    Dim xobj As ObjectId() = wpL.ToArray
                    ed.SetImpliedSelection(xobj)
                End If
                dTrans.Commit()
            End Using
        End Using
        Autodesk.AutoCAD.ApplicationServices.Application.UpdateScreen()
    End Sub
    Public Sub CLDS_SelectWPsByLVCable(ByVal p_lv As System.Windows.Forms.ListView, ByRef wpL As List(Of ObjectId))
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim zobj() As ObjectId
        Try
            ed.SetImpliedSelection(zobj)
        Catch ex As Exception
        End Try
        wpL.Clear()
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim psr As PromptSelectionResult = CLDS_SelectWPs(dTrans, ed)
                If psr.Status = PromptStatus.OK Then
                    For Each lvi As System.Windows.Forms.ListViewItem In p_lv.SelectedItems
                        Debug.Print("Look for cable " & lvi.Text)
                        CLDS_FindAllWP(dTrans, "", psr, wpL, lvi.Text)
                        Debug.Print("Cable list size " & Str$(wpL.Count))
                    Next
                    Dim xobj As ObjectId() = wpL.ToArray
                    ed.SetImpliedSelection(xobj)
                End If
                dTrans.Commit()
            End Using
        End Using
        Autodesk.AutoCAD.ApplicationServices.Application.UpdateScreen()
    End Sub
#End Region
#Region "Building functions"
    Public Function CLDS_GetBuildingFromDwg() As String
        Dim arr As String(,)
        Dim acc As Collection
        Dim name As String = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Name
        name = Path.GetFileNameWithoutExtension(name)
        Dim n As Integer = CLDS_Query(Nothing, 1, "DRAWING", "BUILDING", name, arr, acc)
        If n <= 0 Then
            MsgBox("WARNING: no number ranges found in RCMS applicable to this drawing", MsgBoxStyle.Exclamation, "RCMS")
            Return "-"
        End If
        Return arr(acc("BUILDING_BLDNG"), 1)
    End Function
    Public Function CLDS_GetBuilding(ByVal p_dialog As RCMS_Container) As String
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim name As String = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Name
        name = Path.GetFileNameWithoutExtension(name)
        Dim b As String = CLDS_GetBuildingFromDwg()
        If b = "" Or b = "-" Then
            Dim i As Integer = InStr(name, "_")
            If i > 0 Then
                b = Mid$(name, 1, i - 1)
            Else
                i = InStr(name, "-")
                If i > 0 Then
                    b = Mid$(name, 1, i - 1)
                Else
                    MsgBox("WARNING: unable to determine building from drawing name", MsgBoxStyle.Exclamation, "RCMS")
                    b = "-"
                End If
            End If
            'Using acLckDoc As DocumentLock = doc.LockDocument()
            'Using dTrans As Transaction = doc.TransactionManager.StartTransaction
            'Dim psr As PromptSelectionResult = CLDS_SelectWPs(dTrans, ed)
            'If Not psr.Value Is Nothing Then
            'If psr.Value.Count > 0 Then
            'Dim wpO As ObjectId = psr.Value.GetObjectIds.ElementAt(0)
            'Dim wpB As BlockReference = TryCast(wpO.GetObject(OpenMode.ForRead), BlockReference)
            'If Not wpB Is Nothing Then
            'Dim bld As String = CLDS_GetBlockAttr(wpB, pPrefs.t_fpid)
            'If bld <> "" Then
            'Dim fld() As String = Split(bld, "-", -1, CompareMethod.Text)
            'If UBound(fld) = 3 Then
            'b = fld(1)
            'End If
            'End If
            'End If
            'End If
            'End If
            'dTrans.Commit()
            'End Using
            'End Using
        End If
        If b = "" Or b = "-" Then
            Return "-"
        End If
        Dim arr As String(,)
        Dim acc As Collection
        Dim n As Integer = CLDS_Query(Nothing, 1, "DRAWING", "CAMPUS", b, arr, acc)
        If n <= 0 Then
            MsgBox("ERROR: campus not found for building " & b, MsgBoxStyle.Critical, "RCMS")
            Return "-"
        End If
        p_dialog.pCampus = arr(acc("CAMPUS_NAME"), 1)
        Return b
    End Function
#End Region
#Region "Cable functions"
    Public Function CLDS_ValidWP(ByVal p_wp As String, ByVal p_v As Integer, ByVal p_d As Integer, ByVal p_a As Integer, ByVal p_c As Integer, ByVal p_f As Integer) As Boolean
        If p_wp = "-" Then
            Return true
        End If
        Dim s As String() = dWP(p_wp)
        If s(6) = "N" Then
            Return True
        End If
        If p_v <= Val(s(1)) And p_d <= Val(s(2)) And p_a <= Val(s(3)) And p_c <= Val(s(4)) And p_f <= Val(s(5)) Then
            Return True
        Else
            Return False
        End If
    End Function
    Public Function CLDS_CheckValidWP(ByVal p_wpcb As System.Windows.Forms.ComboBox, ByVal p_dialog As RCMS_Container) As Boolean
        Dim c(6) As Integer
        For i As Integer = 1 To 6
            c(i) = 0
        Next
        For i As Integer = 1 To 10
            Dim n As String = Trim(Str$(i))
            If i < 10 Then
                n = "0" & n
            End If
            Dim ct As System.Windows.Forms.TextBox = p_dialog.gbCables.Controls("tbCable" & n)
            If ct.Text <> "" Then
                Dim sf As String = Mid$(ct.Text, Len(ct.Text))
                If sf = "V" Then
                    c(1) += 1
                ElseIf sf = "D" Then
                    c(2) += 1
                ElseIf sf = "A" Then
                    c(3) += 1
                ElseIf sf = "C" Then
                    c(4) += 1
                ElseIf sf = "F" Then
                    c(5) += 1
                End If
            End If
        Next
        Dim v As Boolean = CLDS_ValidWP(p_wpcb.Text, c(1), c(2), c(3), c(4), c(5))
        For Each wp As CLDS_ColourComboItem In p_wpcb.Items
            If CLDS_ValidWP(wp.Text, c(1), c(2), c(3), c(4), c(5)) Then
                wp.BColor = System.Drawing.Color.White
                wp.FColor = System.Drawing.SystemColors.WindowText
            Else
                wp.BColor = System.Drawing.Color.Crimson
                wp.FColor = System.Drawing.Color.White
            End If
        Next
        p_wpcb.Refresh()
        Return v
    End Function
    Public Function CLDS_ValidCableID(ByVal p_id As String, Optional ByVal p_final As Boolean = False) As Boolean
        Dim p As Integer = 0
        Dim n As Integer = 0
        Dim s As Integer = 0
        For Each c As Char In p_id
            If IsNumeric(c) Then
                If n = 0 Then
                    n = 1
                Else
                    If s > 0 Then
                        'If p_final Then
                        'MsgBox("Invalid cable ID format", MsgBoxStyle.Critical, "RCMS AutoCAD")
                        'End If
                        Return False    ' Digit after suffix
                    End If
                End If
            Else
                If s > 0 Then
                    'If p_final Then
                    'MsgBox("Single character suffix required in cable ID", MsgBoxStyle.Critical, "RCMS AutoCAD")
                    'End If
                    Return False        ' Suffix more than one character
                ElseIf n > 0 Then
                    s = 1
                    Dim u As Char = UCase(c)
                    If Not (u = "D" Or u = "V" Or u = "C" Or u = "A" Or u = "F") Then
                        'If p_final Then
                        'MsgBox("Invalid character suffix in cable ID", MsgBoxStyle.Critical, "RCMS AutoCAD")
                        'End If
                        Return False    ' Invalid suffix character
                    End If
                Else
                    p = 1
                End If
            End If
        Next
        If p_final Then
            If n = 0 Or s = 0 Then
                'MsgBox("Invalid cable ID format", MsgBoxStyle.Critical, "RCMS AutoCAD")
                Return False
            End If
        End If
        Return True
    End Function
    Public Sub CLDS_Autofill(ByVal p_dialog As RCMS_Container)
        Dim arr As String(,)
        Dim acc As Collection
        Dim a_t(10) As String
        Dim t As String
        Dim i As Integer
        Dim id As String
        Dim f As String
        Dim m As Integer

        If p_dialog.cxModel.Text = "-" Then
            MsgBox("Please specify WP model first")
        End If
        f = p_dialog.cxFloor.Text
        If f = "" Then
            MsgBox("Please specify floor first")
        End If

        Dim r As Integer = CLDS_Query(Nothing, 1, "FACEPLATE", "WPPORT", p_dialog.cxModel.Text, arr, acc)
        If r < 0 Then
            Exit Sub
        End If

        For i = 1 To r - 1
            a_t(i) = arr(0, i)
        Next i

        t = "-"
        For i = 1 To 10
            If i > r - 1 Then
                id = ""
            Else
                If a_t(i) <> t Then
                    m = 1
                    t = a_t(i)
                Else
                    m = m + 1
                End If
                id = CLDS_NextCableID(p_dialog.tbZone.Text, a_t(i), m)
            End If
            If i = 1 Then
                p_dialog.tbCable01.Text = id
            ElseIf i = 2 Then
                p_dialog.tbCable02.Text = id
            ElseIf i = 3 Then
                p_dialog.tbCable03.Text = id
            ElseIf i = 4 Then
                p_dialog.tbCable04.Text = id
            ElseIf i = 5 Then
                p_dialog.tbCable05.Text = id
            ElseIf i = 6 Then
                p_dialog.tbCable06.Text = id
            ElseIf i = 7 Then
                p_dialog.tbCable07.Text = id
            ElseIf i = 8 Then
                p_dialog.tbCable08.Text = id
            ElseIf i = 9 Then
                p_dialog.tbCable09.Text = id
            ElseIf i = 10 Then
                p_dialog.tbCable10.Text = id
            End If
        Next i

    End Sub
    Public Function CLDS_NextCableID(ByVal p_zone As String, ByVal p_type As String, ByVal p_offset As Integer) As String
        Dim arr As String(,)
        Dim acc As Collection
        Dim v_zone As String = p_zone
        If v_zone = "" Then
            v_zone = "ZONE-0"
        End If
        If InStr(v_zone, "ZONE-") = 0 Then
            v_zone = "ZONE-" & v_zone
        End If
        Dim args As String
        CLDS_NextCableID = ""
        Dim name As String = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Name
        name = Path.GetFileNameWithoutExtension(name)
        args = name + ":" + v_zone + ":" + p_type + ":" + Trim$(Str$(p_offset))
        Dim r As Integer = CLDS_Query(Nothing, 1, "DRAWING", "NEXTNO", args, arr, acc)
        If r < 0 Then
            Return "ERROR!"
        End If
        Return arr(acc("NEXTNO_NEXTNO"), 1)
    End Function
    Public Function CLDS_AddV9Cable(ByVal p_b As String, ByVal p_fp As String, ByVal a_cab() As String) As String
        Dim arr As String(,)
        Dim acc As Collection
        Dim args As String
        Dim i As Integer

        args = p_b + ":" + p_fp
        For i = 1 To 10
            If a_cab(i) <> "" Then
                args = args + ":" + a_cab(i)
            End If
        Next i
        Dim r As Integer = CLDS_Query(Nothing, 1, "FACEPLATE", "CABLE", args, arr, acc)
        If r < 0 Then
            MsgBox("Problem adding faceplate cable" & Chr(10) & CMERR, MsgBoxStyle.Critical, "RCMS AutoCAD")
            Return "ERROR"
        End If
        Return "OK"
    End Function
#End Region
#Region "List functions"
    Public Function CLDS_CheckFPID(ByVal p_bldng As String, ByVal p_room As String, ByVal p_fpno As String, ByVal p_fpid As String, ByVal p_floor As String) As String
        If InStr(p_fpid, "#", CompareMethod.Text) > 0 Then
            Return "ID"
        End If
        If InStr(p_floor, "#", CompareMethod.Text) > 0 Then
            Return "FLOOR"
        End If
        Dim a As String() = Split(p_fpid, "-", -1)
        If UBound(a, 1) <> 3 Then
            Return "ID"
        End If
        If a(0) <> "FP" Then
            Return "ID"
        End If
        If a(1) <> p_bldng Then
            Return "BLDNG"
        End If
        If a(2) <> p_room Then
            Return "ROOM"
        End If
        If a(3) <> p_fpno Then
            Return "FPNO"
        End If
        Return "-"
    End Function
    Public Function CLDS_CheckDupFPID(ByVal p_trans As Transaction, ByVal p_psr As PromptSelectionResult, ByVal p_fpid As String, ByVal p_wp As BlockReference)
        Dim dupO As ObjectId = CLDS_FindWP(p_trans, p_fpid, p_psr, p_wp)
        If Not dupO.IsNull Then
            Return "DUP"
        End If
        Return "-"
    End Function
    Public Function CLDS_CheckCableID(ByVal p_cabid As String) As String
        Dim c As String = UCase(Mid(p_cabid, Len(p_cabid), 1))
        If Not (c = "V" Or c = "D" Or c = "A" Or c = "C" Or c = "F") Then
            Return "ID1"
        End If
        Dim s As String = Mid(p_cabid, 1, Len(p_cabid) - 1)
        Dim i As Integer = 1
        While c <> ""
            c = Mid(s, i, 1)
            If c = "" Then
                Exit While
            End If
            If Asc(c) >= Asc("0") And Asc(c) <= Asc("9") Then
                Exit While
            End If
            i = i + 1
        End While
        If c = "" Then
            Return "ID2"
        End If
        While c <> ""
            c = Mid(s, i, 1)
            If c = "" Then
                Exit While
            End If
            If Asc(c) < Asc("0") Or Asc(c) > Asc("9") Then
                Return "ID3"
            End If
            i = i + 1
        End While
        Return "-"
    End Function
    Public Function CLDS_CheckDupCable(ByVal p_lv As System.Windows.Forms.ListView, ByVal p_cabid As String)
        For Each lvi As System.Windows.Forms.ListViewItem In p_lv.Items
            If lvi.Text = p_cabid Then
                lvi.SubItems(2).Text = "DUP"
                Return "DUP"
            End If
        Next
        Return "-"
    End Function
    Public Function CLDS_ShowList(ByVal p_dialog As RCMS_Container, Optional ByVal p_toggle As Boolean = True) As Integer
        If pRCMSDialog.pBuilding = "" Or pRCMSDialog.pBuilding = "-" Then
            MsgBox("Building not set for this drawing", MsgBoxStyle.Critical, "RCMS AutoCAD")
            Return 4
        End If
        Dim tc As System.Windows.Forms.TabControl = p_dialog.tcList
        Dim lvFP As System.Windows.Forms.ListView = p_dialog.lvFaceplates
        Dim lvCB As System.Windows.Forms.ListView = p_dialog.lvCables
        If tc.Visible And p_toggle Then
            tc.Visible = False
            p_dialog.gbCables.Visible = True
            Return 0
        End If
        Dim result As Integer = 0
        p_dialog.gbCables.Visible = False
        tc.Visible = True
        tc.Size = p_dialog.gbCables.Size
        tc.Location = p_dialog.gbCables.Location
        Dim w As Integer = tc.Size.Width
        Dim h As Integer = tc.Size.Height
        w = w - 10
        h = h - 30
        lvFP.Size = New System.Drawing.Size(w, h)
        lvCB.Size = lvFP.Size
        lvFP.Clear()
        lvFP.Columns.Add("FP ID")
        lvFP.Columns.Add("Floor")
        lvFP.Columns.Add("Room")
        lvFP.Columns.Add("Model")
        lvFP.Columns.Add("Status")
        lvFP.Columns.Add("Project")
        lvFP.Columns.Add("Phase")
        lvFP.Columns.Add("FPNo")
        lvFP.Columns.Add("Handle")
        lvCB.Clear()
        lvCB.Columns.Add("Cable")
        lvCB.Columns.Add("FP ID")
        lvCB.Columns.Add("Status")
        Dim doc As Document
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim fpSE As BlockReference = CLDS_SingleWP()
                Dim fpSID As String = "-"
                If Not fpSE Is Nothing Then
                    fpSID = CLDS_GetBlockAttr(fpSE, pPrefs.t_fpid)
                End If
                Dim psr As PromptSelectionResult = CLDS_SelectWPs(dTrans, doc.Editor)
                If psr.Status = PromptStatus.OK Then
                    If Not psr.Value Is Nothing Then
                        For Each wpOID As ObjectId In psr.Value.GetObjectIds
                            Dim wpE As BlockReference = DirectCast(wpOID.GetObject(OpenMode.ForRead), BlockReference)
                            Dim fpID As String = CLDS_GetBlockAttr(wpE, pPrefs.t_fpid)
                            Dim room As String = CLDS_GetBlockAttr(wpE, pPrefs.t_room)
                            Dim flor As String = CLDS_GetBlockAttr(wpE, pPrefs.t_flor)
                            Dim fpno As String = CLDS_GetBlockAttr(wpE, pPrefs.t_fpno)
                            Dim wpID As String = CLDS_GetBlockAttr(wpE, pPrefs.t_wpid)
                            Dim stat As String = CLDS_CheckFPID(pRCMSDialog.pBuilding, room, fpno, fpID, flor)
                            If stat = "-" Then
                                stat = CLDS_CheckDupFPID(dTrans, psr, fpID, wpE)
                            End If
                            If stat <> "-" Then
                                result = result Or 2
                            End If
                            Dim rb As ResultBuffer = CLDS_GetXRecord(dTrans, wpE)
                            Dim fpproj As String
                            Dim fpphase As String
                            If rb Is Nothing Then
                                fpproj = ""
                                fpphase = ""
                            Else
                                Dim ra As TypedValue() = rb.AsArray
                                fpproj = ra(0).Value
                                fpphase = ra(1).Value
                            End If
                            Dim hand As String = Trim(Str$(wpE.ObjectId.Handle.Value))
                            Dim lvi As New System.Windows.Forms.ListViewItem
                            lvi.Text = fpID
                            lvi.SubItems.Add(flor)
                            lvi.SubItems.Add(room)
                            lvi.SubItems.Add(wpID)
                            lvi.SubItems.Add(stat)
                            lvi.SubItems.Add(fpproj)
                            lvi.SubItems.Add(fpphase)
                            lvi.SubItems.Add(fpno)
                            lvi.SubItems.Add(hand)
                            lvFP.Items.Add(lvi)
                            For i = 1 To pPrefs.x_cbno
                                Dim n As String = Trim(Str$(i))
                                Dim c As String = CLDS_GetBlockAttr(wpE, pPrefs.t_cbid & n)
                                If c <> "" And c <> "-" Then
                                    Dim csta As String = CLDS_CheckCableID(c)
                                    If csta = "-" Then
                                        csta = CLDS_CheckDupCable(lvCB, c)
                                    End If
                                    If csta <> "-" Then
                                        If csta = "DUP" Then
                                            result = result Or 1
                                        Else
                                            result = result Or 2
                                        End If
                                    End If
                                    Dim lvc As New System.Windows.Forms.ListViewItem
                                    lvc.Text = c
                                    lvc.SubItems.Add(fpID)
                                    lvc.SubItems.Add(csta)
                                    lvCB.Items.Add(lvc)
                                End If
                            Next
                        Next
                        For i As Integer = 0 To lvFP.Columns.Count - 1
                            lvFP.Columns(i).Width = -2
                        Next
                        lvFP.Columns(7).Width = 0
                        lvFP.Columns(8).Width = 0
                        For i As Integer = 0 To lvCB.Columns.Count - 1
                            lvCB.Columns(i).Width = -2
                        Next
                        lvCB.Sorting = Windows.Forms.SortOrder.Ascending
                        lvCB.ListViewItemSorter = New RCMS_CBLVSorter(0, lvCB.Sorting)
                        lvCB.Sort()
                        lvFP.Sorting = Windows.Forms.SortOrder.Ascending
                        lvFP.ListViewItemSorter = New RCMS_FPLVSorter(0, lvFP.Sorting)
                        Debug.Print("Before sort " & lvFP.Items(0).Text)
                        lvFP.Sort()
                        Debug.Print("After sort " & lvFP.Items(0).Text)
                        For Each lvi As System.Windows.Forms.ListViewItem In lvFP.Items
                            If lvi.Text = fpSID Then
                                lvi.Selected = True
                                Exit For
                            End If
                        Next
                        lvFP.Update()
                        lvCB.Update()
                        tc.Update()
                    End If
                End If
                dTrans.Commit()
            End Using
        End Using
        Return result
    End Function
#End Region
#Region "WP edit"
    Public Function CLDS_CheckDupFP(ByVal p_dialog As RCMS_Container) As Boolean
        Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        If p_dialog.pBuilding = "" Or p_dialog.pBuilding = "-" Or p_dialog.pRoom = "" Or p_dialog.pRoom = "-" Then
            p_dialog.tbFPID.Text = ""
            p_dialog.tbFPID.BackColor = System.Drawing.SystemColors.Control
            p_dialog.tbFPID.ForeColor = System.Drawing.SystemColors.WindowText
            p_dialog.tbFPID.Update()
            Return True
        End If
        Dim fpbase As String = "FP-" & p_dialog.pBuilding & "-" & p_dialog.pRoom & "-"
        Dim fpno As String = Trim(Str$(p_dialog.udFPNo.Value))
        Dim fpid As String = fpbase & fpno
        If fpno = "0" Then
            p_dialog.tbFPID.Text = ""
            Return True
        End If
        p_dialog.tbFPID.Text = fpid
        Dim limit As Integer = 0
        p_dialog.btDeleteWP.Enabled = False
        If (p_dialog.pMode = "UPDATE" Or p_dialog.pMode = "NEW") And fpid = p_dialog.pFPID Then
            limit = 1
            p_dialog.btDeleteWP.Enabled = True
        ElseIf p_dialog.pMode = "" Then
            limit = 1
        End If
        Dim result As Boolean = True
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim psr As PromptSelectionResult = CLDS_SelectWPs(dTrans, doc.Editor)
                Dim dList As List(Of ObjectId) = New List(Of ObjectId)
                Debug.Print("Dup find FP " & fpid)
                Debug.Print("Dup limit " & Str$(limit) & ", mode " & p_dialog.pMode & ", FPID " & fpid & ", XFPID " & p_dialog.pFPID)
                CLDS_FindAllWP(dTrans, fpid, psr, dList, "")
                Debug.Print("Dup list size " & Str$(dList.Count))
                If dList.Count > limit Then
                    Dim zobj() As ObjectId
                    Try
                        doc.Editor.SetImpliedSelection(zobj)
                    Catch ex As Exception
                    End Try
                    Dim xObj As ObjectId() = dList.ToArray
                    doc.Editor.SetImpliedSelection(xObj)
                    p_dialog.tbFPID.BackColor = System.Drawing.Color.Crimson
                    p_dialog.tbFPID.ForeColor = System.Drawing.Color.White
                    result = False
                Else
                    If (p_dialog.pMode = "ADD" Or p_dialog.pMode = "UPDATE" Or p_dialog.pMode = "NEW") And Not fpBlock.IsNull Then
                        CLDS_SelectObject(fpBlock)
                    End If
                    p_dialog.tbFPID.BackColor = System.Drawing.SystemColors.Control
                    p_dialog.tbFPID.ForeColor = System.Drawing.SystemColors.WindowText
                    result = True
                End If
                p_dialog.tbFPID.Update()
                dTrans.Commit()
            End Using
        End Using
        Return result
    End Function
    Public Sub CLDS_NextFP(ByVal p_dialog As RCMS_Container)
        If p_dialog.pRoom = "" Or p_dialog.pRoom = "-" Then
            p_dialog.udFPNo.Value = 0
            p_dialog.tbFPID.Text = ""
            Exit Sub
        End If
        Dim doc As Document
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Dim fpbase As String = "FP-" & p_dialog.pBuilding & "-" & p_dialog.pRoom & "-"
        Dim fpid As String = ""
        Dim n As String = ""
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim psr As PromptSelectionResult = CLDS_SelectWPs(dTrans, doc.Editor)
                For i As Integer = 1 To 10000
                    fpid = fpbase & Trim(Str$(i))
                    Dim wpO As ObjectId = CLDS_FindWP(dTrans, fpid, psr)
                    If wpO.IsNull Then
                        n = Trim(Str$(i))
                        Exit For
                    End If
                Next
                dTrans.Commit()
            End Using
        End Using
        If n <> "" Then
            p_dialog.udFPNo.Value = Val(n)
            p_dialog.tbFPID.Text = fpid
        End If
    End Sub
    Public Sub CLDS_ClearCables(ByVal p_dialog As RCMS_Container, Optional ByVal p_hash As Boolean = False)
        For i = 1 To pPrefs.x_cbno
            Dim n As String = Trim(Str$(i))
            If Len(n) < 2 Then
                n = "0" & n
            End If
            Dim cf As System.Windows.Forms.TextBox = p_dialog.gbCables.Controls("tbCable" & n)
            If p_hash Then
                If InStr(cf.Text, "#", CompareMethod.Text) > 0 Then
                    cf.Text = ""
                End If
            Else
                cf.Text = ""
            End If
        Next
    End Sub
    Public Sub CLDS_EnableCables(ByVal p_dialog As RCMS_Container, ByVal p_enabled As Boolean)
        For i = 1 To pPrefs.x_cbno
            Dim n As String = Trim(Str$(i))
            If Len(n) < 2 Then
                n = "0" & n
            End If
            Dim cf As System.Windows.Forms.TextBox = p_dialog.gbCables.Controls("tbCable" & n)
            cf.ReadOnly = (Not p_enabled)
            If cf.ReadOnly Then
                cf.BackColor = System.Drawing.SystemColors.Control
            Else
                cf.BackColor = System.Drawing.Color.White
            End If
        Next
    End Sub
    Public Function CLDS_AddV9Faceplate(ByVal p_b As String, ByVal p_f As String, ByVal p_r As String, ByVal p_fp As String, ByVal p_wp As String, ByVal p_pr As String, ByVal p_ph As String) As String
        Dim arr As String(,)
        Dim acc As Collection
        Dim args As String

        Dim name As String = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Name
        name = Path.GetFileNameWithoutExtension(name)
        args = p_b + ":" + p_f + ":" + p_r + ":" + p_fp + ":" + p_wp + ":" + name + ":" + p_pr + ":" + p_ph

        Dim r As Integer = CLDS_Query(Nothing, 1, "FACEPLATE", "INSERT", args, arr, acc)
        If r < 0 Then
            MsgBox("Problem adding faceplate" & Chr(10) & CMERR, MsgBoxStyle.Critical, "RCMS AutoCAD")
            Return "ERROR"
        End If
        If p_fp = "*END*" Then
            Return "OK:" & arr(acc("INSERT_OK"), 1)
        Else
            Return "OK"
        End If
    End Function
    Public Function CLDS_DeleteV9Faceplate(ByVal p_fpid As String) As String
        Dim arr As String(,)
        Dim acc As Collection
        Dim args As String
        args = p_fpid
        Dim r As Integer = CLDS_Query(Nothing, 1, "FACEPLATE", "DELETE", args, arr, acc)
        If r < 0 Then
            MsgBox("Problem deleting faceplate" & Chr(10) & CMERR, MsgBoxStyle.Critical, "RCMS AutoCAD")
            Return "ERROR"
        End If
        Return "OK"
    End Function
    Public Function CLDS_SyncV9Faceplate(ByVal fpB As BlockReference, ByVal bldng As String) As String
        Dim wpno As String
        Dim fpfloor As String
        Dim fproom As String
        Dim fpno As String
        Dim fpid As String
        Dim fpproj As String
        Dim fpphase As String
        Dim a_c(11) As String
        Dim r As String

        fpid = ""
        fpfloor = ""
        fproom = ""
        wpno = ""
        fpno = ""
        fpproj = ""
        fpphase = ""

        Dim doc As Document
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                If Not fpB Is Nothing Then
                    fpid = CLDS_GetBlockAttr(fpB, pPrefs.t_fpid)
                    fpfloor = CLDS_GetBlockAttr(fpB, pPrefs.t_flor)
                    fproom = CLDS_GetBlockAttr(fpB, pPrefs.t_room)
                    wpno = CLDS_GetBlockAttr(fpB, pPrefs.t_wpid)
                    fpno = CLDS_GetBlockAttr(fpB, pPrefs.t_fpno)
                    For i = 1 To pPrefs.x_cbno
                        Dim n As String = Trim(Str$(i))
                        Dim c As String = CLDS_GetBlockAttr(fpB, pPrefs.t_cbid & n)
                        If Len(n) < 2 Then
                            n = "0" & n
                        End If
                        a_c(i) = c
                    Next
                End If
                Dim rb As ResultBuffer = CLDS_GetXRecord(dTrans, fpB)
                If rb Is Nothing Then
                    fpproj = ""
                    fpphase = ""
                Else
                    Dim ra As TypedValue() = rb.AsArray
                    fpproj = ra(0).Value
                    fpphase = ra(1).Value
                End If
                dTrans.Commit()
            End Using
        End Using
        If wpno = "" Or fproom = "" Or fpno = "" Or fpid = "" Then
            Debug.Print("Insufficient block parameters")
            Return "OK"
        End If
        r = CLDS_AddV9Faceplate(bldng, fpfloor, fproom, fpid, wpno, fpproj, fpphase)
        Debug.Print("Faceplate " + fpid + " " + r)
        If r = "OK" Then
            r = CLDS_AddV9Cable(bldng, fpid, a_c)
            Debug.Print("Cable " + fpid + " " + r)
            If r <> "OK" Then
                CLDS_WriteMessage(doc.Editor, Chr(10) & fpid & " " & r & Chr(10))
            End If
        Else
            CLDS_WriteMessage(doc.Editor, Chr(10) & fpid & " " & r & Chr(10))
        End If
        Return r
    End Function
    Public Sub CLDS_SyncAll()
        If pRCMSDialog.pBuilding = "" Or pRCMSDialog.pBuilding = "-" Then
            MsgBox("Building not set for this drawing", MsgBoxStyle.Critical, "RCMS AutoCAD")
            Exit Sub
        End If
        Dim check As Integer = CLDS_ShowList(pRCMSDialog, False)
        If check > 1 Then
            MsgBox("Errors in FPs/cables prevent synchronization", MsgBoxStyle.Critical, "RCMS AutoCAD")
            Exit Sub
        End If
        If check > 0 Then
            Dim m As MsgBoxResult = MsgBox("Duplicate cables found!" & Chr(10) & Chr(10) & "Continue with sync?", MsgBoxStyle.OkCancel, "RCMS AutoCAD")
            If m = MsgBoxResult.Cancel Then
                Exit Sub
            End If
        End If
        Dim doc As Document
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Dim c As Integer = 0, e As Integer = 0, f As Integer = 0, d As Integer = 0, r As String = ""
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim psr As PromptSelectionResult = CLDS_SelectWPs(dTrans, doc.Editor)
                If psr.Status = PromptStatus.OK Then
                    If Not psr.Value Is Nothing Then
                        Dim w As Integer = 0
                        pRCMSDialog.pbSync.Visible = True
                        pRCMSDialog.pbSync.Maximum = psr.Value.Count
                        pRCMSDialog.pbSync.Value = w
                        For Each wpOID As ObjectId In psr.Value.GetObjectIds
                            Dim wpE As BlockReference = DirectCast(wpOID.GetObject(OpenMode.ForRead), BlockReference)
                            r = ""
                            If (c + e + f) = 0 Then
                                r = CLDS_AddV9Faceplate(pRCMSDialog.pBuilding, "-", "-", "*START*", "-", "", "")
                                If r <> "OK" Then
                                    MsgBox("Unable to synchronize with RCMS", MsgBoxStyle.Critical, "RCMS AutoCAD")
                                    f = f + 1
                                End If
                            End If
                            If f = 0 Then
                                r = CLDS_SyncV9Faceplate(wpE, pRCMSDialog.pBuilding)
                                If r = "OK" Then
                                    c = c + 1
                                Else
                                    e = e + 1
                                End If
                                w = w + 1
                                pRCMSDialog.pbSync.Value = w
                            End If
                        Next
                        pRCMSDialog.pbSync.Visible = False
                    End If
                End If
                If (c + e) > 0 Then
                    r = CLDS_AddV9Faceplate(pRCMSDialog.pBuilding, "-", "-", "*END*", "-", "", "")
                    If Mid(r, 1, 3) = "OK:" Then
                        d = Val(Mid(r, 4))
                    End If
                End If
                dTrans.Commit()
            End Using
        End Using
        CLDS_RangeTable(False)
        If f = 0 Then
            MsgBox("Synchronized " & c & " OK, " & e & " errors, " & d & " deletions", MsgBoxStyle.Information, "RCMS AutoCAD")
        End If
    End Sub
    Public Sub CLDS_AddWP(ByVal p_dialog As RCMS_Container)
        Dim zobj() As ObjectId
        Dim doc As Document
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Try
            doc.Editor.SetImpliedSelection(zobj)
        Catch ex As Exception
        End Try
        If p_dialog.tcList.Visible Then
            CLDS_ShowList(p_dialog, True)
        End If
        CLDS_CancelWP(p_dialog, False)
        p_dialog.btSearch.Enabled = False
        p_dialog.btAddWP.Enabled = False
        p_dialog.btEditWP.Enabled = False
        p_dialog.btDeleteWP.Enabled = False
        p_dialog.btCancel.Enabled = False
        p_dialog.btSave.Enabled = False
        p_dialog.btAutofill.Enabled = False
        p_dialog.btRange.Enabled = False
        p_dialog.btZone.Enabled = False
        p_dialog.btList.Enabled = False
        p_dialog.btSync.Enabled = False
        p_dialog.btExcel.Enabled = False
        p_dialog.cxBuilding.Enabled = False
        p_dialog.cxFloor.Enabled = False
        p_dialog.cxRoom.Enabled = False
        p_dialog.cxModel.Enabled = False
        p_dialog.udFPNo.ReadOnly = True
        p_dialog.tbProject.ReadOnly = True
        p_dialog.tbPhase.ReadOnly = True
        CLDS_EnableCables(p_dialog, False)
        fpBlock = CLDS_PointWP(p_dialog)
        If fpBlock.IsNull Then
            CLDS_CancelWP(p_dialog)
        Else
            CLDS_SelectObject(fpBlock)
            p_dialog.tbZone.Text = CLDS_PointInZone(fpBlock)
            p_dialog.btSave.Enabled = True
            p_dialog.btDeleteWP.Enabled = False
            p_dialog.btCancel.Enabled = True
            p_dialog.btAutofill.Enabled = True
            p_dialog.cxFloor.Enabled = True
            p_dialog.cxRoom.Enabled = True
            p_dialog.cxModel.Enabled = True
            p_dialog.udFPNo.ReadOnly = False
            p_dialog.tbProject.ReadOnly = False
            p_dialog.tbPhase.ReadOnly = False
            If p_dialog.pBuilding = "" Then
                p_dialog.cxBuilding.Enabled = True
            Else
                p_dialog.cxFloor.Text = p_dialog.pFloor
                p_dialog.cxRoom.Text = p_dialog.pRoom
                CLDS_NextFP(p_dialog)
            End If
            CLDS_ClearCables(p_dialog)
            CLDS_EnableCables(p_dialog, True)
        End If
    End Sub
    Public Function CLDS_ISNewWP(ByVal p_dialog As RCMS_Container) As Boolean
        If InStr(p_dialog.cxBuilding.Text, "#", CompareMethod.Text) > 0 Then
            Return True
        End If
        If InStr(p_dialog.cxFloor.Text, "#", CompareMethod.Text) > 0 Then
            Return True
        End If
        If InStr(p_dialog.cxRoom.Text, "#", CompareMethod.Text) > 0 Then
            Return True
        End If
        If InStr(p_dialog.cxModel.Text, "#", CompareMethod.Text) > 0 Then
            Return True
        End If
        If InStr(p_dialog.cxModel.Text, "#", CompareMethod.Text) > 0 Then
            Return True
        End If
        If InStr(p_dialog.tbFPID.Text, "#", CompareMethod.Text) > 0 Then
            Return True
        End If
        For i = 1 To pPrefs.x_cbno
            Dim n As String = Trim(Str$(i))
            If Len(n) < 2 Then
                n = "0" & n
            End If
            Dim cf As System.Windows.Forms.TextBox = p_dialog.gbCables.Controls("tbCable" & n)
            If InStr(cf.Text, "#", CompareMethod.Text) > 0 Then
                Return True
            End If
        Next
        Return False
    End Function
    Public Function CLDS_HasNoCables(ByVal p_dialog As RCMS_Container) As Boolean
        For i = 1 To pPrefs.x_cbno
            Dim n As String = Trim(Str$(i))
            If Len(n) < 2 Then
                n = "0" & n
            End If
            Dim cf As System.Windows.Forms.TextBox = p_dialog.gbCables.Controls("tbCable" & n)
            If cf.Text <> "" Then
                Return False
            End If
        Next
        Return True
    End Function
    Public Sub CLDS_UpdateWP(ByVal p_dialog As RCMS_Container)
        If p_dialog.tcList.Visible Then
            CLDS_ShowList(p_dialog, True)
        End If
        p_dialog.btSearch.Enabled = False
        p_dialog.btAddWP.Enabled = False
        p_dialog.btEditWP.Enabled = False
        p_dialog.btDeleteWP.Enabled = True
        p_dialog.btCancel.Enabled = True
        p_dialog.btSave.Enabled = True
        p_dialog.btAutofill.Enabled = False
        p_dialog.btRange.Enabled = False
        p_dialog.btZone.Enabled = False
        p_dialog.btList.Enabled = False
        p_dialog.btSync.Enabled = False
        p_dialog.btExcel.Enabled = False
        p_dialog.cxBuilding.Enabled = False
        p_dialog.cxFloor.Enabled = False
        p_dialog.cxRoom.Enabled = False
        p_dialog.cxModel.Enabled = True
        p_dialog.udFPNo.ReadOnly = False
        p_dialog.tbProject.ReadOnly = False
        p_dialog.tbPhase.ReadOnly = False
        CLDS_EnableCables(p_dialog, True)
        p_dialog.pMode = "UPDATE"
        If CLDS_ISNewWP(p_dialog) Then
            p_dialog.tbZone.Text = CLDS_PointInZone(fpBlock)
            p_dialog.btSave.Enabled = True
            p_dialog.btDeleteWP.Enabled = True
            p_dialog.btCancel.Enabled = True
            p_dialog.btAutofill.Enabled = True
            p_dialog.cxFloor.Enabled = True
            p_dialog.cxRoom.Enabled = True
            p_dialog.cxModel.Enabled = True
            p_dialog.udFPNo.ReadOnly = False
            p_dialog.tbProject.ReadOnly = False
            p_dialog.tbPhase.ReadOnly = False
            If p_dialog.pBuilding = "" Then
                p_dialog.cxBuilding.Enabled = True
            End If
            If InStr(p_dialog.cxFloor.Text, "#", CompareMethod.Text) > 0 Then
                p_dialog.cxFloor.Text = p_dialog.pFloor
            End If
            If InStr(p_dialog.cxRoom.Text, "#", CompareMethod.Text) > 0 Then
                p_dialog.cxRoom.Text = p_dialog.pRoom
            End If
            If InStr(p_dialog.tbFPID.Text, "#", CompareMethod.Text) > 0 Then
                CLDS_NextFP(p_dialog)
            End If
            CLDS_ClearCables(p_dialog, True)
            p_dialog.pMode = "NEW"
        Else
            If CLDS_HasNoCables(p_dialog) Then
                p_dialog.tbZone.Text = CLDS_PointInZone(fpBlock)
                p_dialog.btAutofill.Enabled = True
            End If
            p_dialog.pFloor = p_dialog.cxFloor.Text
            p_dialog.pRoom = p_dialog.cxRoom.Text
            p_dialog.pModel = p_dialog.cxModel.Text
            p_dialog.pFPID = p_dialog.tbFPID.Text
        End If
    End Sub
    Public Sub CLDS_ExecuteQuery(ByVal p_dialog As RCMS_Container)
        Dim doc As Document
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        p_dialog.btEditWP.Enabled = False
        Dim wpB As BlockReference = CLDS_SingleWP()
        Dim wpID As String = ""
        If Not wpB Is Nothing Then
            Using acLckDoc As DocumentLock = doc.LockDocument()
                Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                    wpID = CLDS_GetBlockAttr(wpB, pPrefs.t_fpid)
                    dTrans.Commit()
                End Using
            End Using
        End If
        If wpID = "" Then
            Exit Sub
        Else
            fpBlock = wpB.ObjectId
            Using acLckDoc As DocumentLock = doc.LockDocument()
                Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                    p_dialog.cxFloor.Text = CLDS_GetBlockAttr(wpB, pPrefs.t_flor)
                    p_dialog.cxRoom.Text = CLDS_GetBlockAttr(wpB, pPrefs.t_room)
                    p_dialog.cxModel.Text = CLDS_GetBlockAttr(wpB, pPrefs.t_wpid)
                    If InStr(p_dialog.cxFloor.Text, "#", CompareMethod.Text) = 0 Then
                        p_dialog.pFloor = p_dialog.cxFloor.Text
                    End If
                    If InStr(p_dialog.cxRoom.Text, "#", CompareMethod.Text) = 0 Then
                        p_dialog.pRoom = p_dialog.cxRoom.Text
                    End If
                    If InStr(p_dialog.cxModel.Text, "#", CompareMethod.Text) = 0 Then
                        p_dialog.pModel = p_dialog.cxModel.Text
                    End If
                    If InStr(wpID, "#", CompareMethod.Text) = 0 Then
                        p_dialog.pFPID = wpID
                    End If
                    Try
                        p_dialog.udFPNo.Value = Val(CLDS_GetBlockAttr(wpB, pPrefs.t_fpno))
                    Catch ex As Exception
                        p_dialog.udFPNo.Value = 0
                    End Try
                    p_dialog.tbFPID.Text = wpID
                    For i = 1 To pPrefs.x_cbno
                        Dim n As String = Trim(Str$(i))
                        Dim c As String = CLDS_GetBlockAttr(wpB, pPrefs.t_cbid & n)
                        If Len(n) < 2 Then
                            n = "0" & n
                        End If
                        Dim cf As System.Windows.Forms.TextBox = p_dialog.gbCables.Controls("tbCable" & n)
                        cf.Text = c
                    Next
                    Dim rb As ResultBuffer = CLDS_GetXRecord(dTrans, wpB)
                    If rb Is Nothing Then
                        p_dialog.tbProject.Text = ""
                        p_dialog.tbPhase.Text = ""
                    Else
                        Dim ra As TypedValue() = rb.AsArray
                        p_dialog.tbProject.Text = ra(0).Value
                        p_dialog.tbPhase.Text = ra(1).Value
                    End If
                    'CLDS_SelectObject(wpB.ObjectId, True)
                    'End If
                    'End If
                    dTrans.Commit()
                End Using
            End Using
        End If
        p_dialog.btSearch.Enabled = True
        p_dialog.btAddWP.Enabled = True
        p_dialog.btEditWP.Enabled = True
        p_dialog.btDeleteWP.Enabled = False
        p_dialog.btCancel.Enabled = False
        p_dialog.btSave.Enabled = False
        p_dialog.btAutofill.Enabled = False
        p_dialog.btRange.Enabled = True
        p_dialog.btZone.Enabled = True
        p_dialog.btList.Enabled = True
        p_dialog.btSync.Enabled = True
        p_dialog.btExcel.Enabled = True
        p_dialog.cxBuilding.Enabled = False
        p_dialog.cxFloor.Enabled = False
        p_dialog.cxRoom.Enabled = False
        p_dialog.cxModel.Enabled = False
        p_dialog.udFPNo.ReadOnly = True
        p_dialog.tbFPID.ReadOnly = True
        p_dialog.tbProject.ReadOnly = True
        p_dialog.tbPhase.ReadOnly = True
        CLDS_EnableCables(p_dialog, False)
        'If Not p_dialog.btEditWP.Enabled Then
        'p_dialog.cxFloor.Text = p_dialog.pFloor
        'p_dialog.cxRoom.Text = p_dialog.pRoom
        'p_dialog.tbFPNo.Text = ""
        'p_dialog.tbFPID.Text = ""
        'CLDS_ClearCables(p_dialog)
        'End If
        p_dialog.pMode = ""
    End Sub
    Public Sub CLDS_ShowWP(ByVal p_dialog As RCMS_Container, ByVal p_fpid As String)
        Dim doc As Document
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        If p_fpid = "" Then
            CLDS_CancelWP(p_dialog)
            Exit Sub
        End If
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim wpB As BlockReference
                Dim wpO As ObjectId = CLDS_FindWP(dTrans, p_fpid)
                If Not wpO.IsNull Then
                    wpB = TryCast(wpO.GetObject(OpenMode.ForRead), BlockReference)
                    If Not wpB Is Nothing Then
                        p_dialog.tbFPID.Text = p_fpid
                        p_dialog.cxFloor.Text = CLDS_GetBlockAttr(wpB, pPrefs.t_flor)
                        p_dialog.cxRoom.Text = CLDS_GetBlockAttr(wpB, pPrefs.t_room)
                        p_dialog.cxModel.Text = CLDS_GetBlockAttr(wpB, pPrefs.t_wpid)
                        Try
                            p_dialog.udFPNo.Value = Val(CLDS_GetBlockAttr(wpB, pPrefs.t_fpno))
                        Catch ex As Exception
                            p_dialog.udFPNo.Value = 0
                        End Try
                        For i = 1 To pPrefs.x_cbno
                            Dim n As String = Trim(Str$(i))
                            Dim c As String = CLDS_GetBlockAttr(wpB, pPrefs.t_cbid & n)
                            If Len(n) < 2 Then
                                n = "0" & n
                            End If
                            Dim cf As System.Windows.Forms.TextBox = p_dialog.gbCables.Controls("tbCable" & n)
                            cf.Text = c
                        Next
                        Dim rb As ResultBuffer = CLDS_GetXRecord(dTrans, wpB)
                        If rb Is Nothing Then
                            p_dialog.tbProject.Text = ""
                            p_dialog.tbPhase.Text = ""
                        Else
                            Dim ra As TypedValue() = rb.AsArray
                            p_dialog.tbProject.Text = ra(0).Value
                            p_dialog.tbPhase.Text = ra(1).Value
                        End If
                        p_dialog.btEditWP.Enabled = True
                    End If
                End If
                dTrans.Commit()
            End Using
        End Using
    End Sub
    Public Sub CLDS_ShowSelectedWPs(ByVal p_dialog As RCMS_Container, ByVal wpL As List(Of ObjectId))
        Dim doc As Document
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        p_dialog.tbFPID.Text = ""
        p_dialog.cxFloor.Text = ""
        p_dialog.cxRoom.Text = ""
        p_dialog.cxModel.Text = ""
        p_dialog.udFPNo.Value = 0
        CLDS_ClearCables(p_dialog)
        p_dialog.tbProject.Text = ""
        p_dialog.tbPhase.Text = ""
        fpBlock = ObjectId.Null
        If wpL.Count < 1 Or wpL.Count > 1 Then
            Exit Sub
        End If
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                Dim wpB As BlockReference
                Dim wpO As ObjectId = wpL.Item(0)
                If Not wpO.IsNull Then
                    wpB = TryCast(wpO.GetObject(OpenMode.ForRead), BlockReference)
                    If Not wpB Is Nothing Then
                        p_dialog.cxFloor.Text = CLDS_GetBlockAttr(wpB, pPrefs.t_flor)
                        p_dialog.cxRoom.Text = CLDS_GetBlockAttr(wpB, pPrefs.t_room)
                        p_dialog.cxModel.Text = CLDS_GetBlockAttr(wpB, pPrefs.t_wpid)
                        Try
                            p_dialog.udFPNo.Value = Val(CLDS_GetBlockAttr(wpB, pPrefs.t_fpno))
                        Catch ex As Exception
                            p_dialog.udFPNo.Value = 0
                        End Try
                        p_dialog.tbFPID.Text = CLDS_GetBlockAttr(wpB, pPrefs.t_fpid)
                        For i = 1 To pPrefs.x_cbno
                            Dim n As String = Trim(Str$(i))
                            Dim c As String = CLDS_GetBlockAttr(wpB, pPrefs.t_cbid & n)
                            If Len(n) < 2 Then
                                n = "0" & n
                            End If
                            Dim cf As System.Windows.Forms.TextBox = p_dialog.gbCables.Controls("tbCable" & n)
                            cf.Text = c
                        Next
                        Dim rb As ResultBuffer = CLDS_GetXRecord(dTrans, wpB)
                        If rb Is Nothing Then
                            p_dialog.tbProject.Text = ""
                            p_dialog.tbPhase.Text = ""
                        Else
                            Dim ra As TypedValue() = rb.AsArray
                            p_dialog.tbProject.Text = ra(0).Value
                            p_dialog.tbPhase.Text = ra(1).Value
                        End If
                        p_dialog.btEditWP.Enabled = True
                    End If
                    fpBlock = wpO
                End If
                dTrans.Commit()
            End Using
        End Using
    End Sub
    Public Sub CLDS_DeleteWP(ByVal p_dialog As RCMS_Container)
        If Not (p_dialog.pMode = "UPDATE" Or p_dialog.pMode = "NEW") Then
            Exit Sub
        End If
        If p_dialog.tbFPID.Text <> p_dialog.pFPID Then
            Exit Sub
        End If
        If fpBlock.IsNull Then
            Exit Sub
        End If
        Dim m As MsgBoxResult = MsgBox("Please confirm deletion of " & p_dialog.pFPID, MsgBoxStyle.OkCancel, "RCMS AutoCAD")
        If m <> MsgBoxResult.Ok Then
            Exit Sub
        End If
        Dim r As String = CLDS_DeleteV9Faceplate(p_dialog.pFPID)
        If r = "ERROR" Then
            Exit Sub
        End If
        Dim doc As Document
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Dim fpB As BlockReference = Nothing
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                fpB = TryCast(fpBlock.GetObject(OpenMode.ForWrite), BlockReference)
                If Not fpB Is Nothing Then
                    fpB.Erase()
                End If
                dTrans.Commit()
            End Using
        End Using
        fpBlock = Nothing
        p_dialog.pMode = ""
        CLDS_CancelWP(p_dialog)
        p_dialog.udFPNo.Value = 0
        p_dialog.tbFPID.Text = ""
        CLDS_ClearCables(p_dialog)
        CLDS_RangeTable(False)
    End Sub
    Public Sub CLDS_SaveWP(ByVal p_dialog As RCMS_Container)
        Dim m As String = ""
        If p_dialog.cxBuilding.Text = "" Or p_dialog.cxBuilding.Text = "-" Then
            m = "ERROR: no building specified"
        End If
        If m = "" And (p_dialog.cxFloor.Text = "" Or p_dialog.cxFloor.Text = "-") Then
            m = "ERROR: no floor specified"
        End If
        If m = "" And (p_dialog.cxRoom.Text = "" Or p_dialog.cxRoom.Text = "-") Then
            m = "ERROR: no room specified"
        End If
        If m = "" And (p_dialog.cxModel.Text = "" Or p_dialog.cxModel.Text = "-") Then
            m = "ERROR: no WP model specified"
        End If
        If m = "" And p_dialog.udFPNo.Value = 0 Then
            m = "ERROR: no FP number specified"
        End If
        If m = "" And (p_dialog.tbFPID.Text = "" Or p_dialog.tbFPID.Text = "-") Then
            m = "ERROR: no FP ID specified"
        End If
        p_dialog.tbFPID.Text = Trim(p_dialog.tbFPID.Text)
        If m = "" Then
            Dim xid As String = "FP-" & p_dialog.pBuilding & "-" & p_dialog.cxRoom.Text & "-" & Trim(Str$(p_dialog.udFPNo.Value))
            If p_dialog.tbFPID.Text <> xid Then
                m = "ERROR: FP ID has invalid format (expecting " & xid & ")"
            End If
        End If
        Dim x As Boolean = CLDS_CheckDupFP(pRCMSDialog)
        If m = "" And Not x Then
            m = "ERROR: duplicate FP ID"
        End If
        If m = "" And fpBlock.IsNull Then
            m = "ERROR: no current WP block for update"
        End If

        If m <> "" Then
            MsgBox(m, MsgBoxStyle.Critical, "RCMS")
            Exit Sub
        End If

        x = True
        If m = "" Then
            For i As Integer = 1 To 10
                Dim n As String = Trim(Str$(i))
                If Len(n) < 2 Then
                    n = "0" & n
                End If
                Dim ct As System.Windows.Forms.TextBox = p_dialog.gbCables.Controls("tbCable" & n)
                Dim cv As String = ct.Text
                If cv = "" Then
                    If ct.ReadOnly Then
                        ct.BackColor = System.Drawing.SystemColors.Control
                    Else
                        ct.BackColor = System.Drawing.Color.White
                    End If
                    ct.ForeColor = System.Drawing.SystemColors.WindowText
                Else
                    Dim v As Boolean = CLDS_ValidCableID(cv, True)
                    If v Then
                        If ct.ReadOnly Then
                            ct.BackColor = System.Drawing.SystemColors.Control
                        Else
                            ct.BackColor = System.Drawing.Color.White
                        End If
                        ct.ForeColor = System.Drawing.SystemColors.WindowText
                    Else
                        x = False
                        ct.BackColor = System.Drawing.Color.Crimson
                        ct.ForeColor = System.Drawing.Color.White
                    End If
                End If
            Next
        End If
        If Not x Then
            Exit Sub
        End If

        x = CLDS_CheckValidWP(p_dialog.cxModel, p_dialog)
        If Not x Then
            Dim xm As MsgBoxResult = MsgBox("Cables do not match specified WP model", MsgBoxStyle.OkCancel, "RCMS AutoCAD")
            If xm = MsgBoxResult.Cancel Then
                Exit Sub
            End If
        End If
        Dim doc As Document
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Dim fpB As BlockReference = Nothing
        Using acLckDoc As DocumentLock = doc.LockDocument()
            Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                fpB = TryCast(fpBlock.GetObject(OpenMode.ForWrite), BlockReference)
                CLDS_SetBlockAttr(fpB, pPrefs.t_flor, p_dialog.cxFloor.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_room, p_dialog.cxRoom.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_wpid, p_dialog.cxModel.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_fpno, Trim(Str$(p_dialog.udFPNo.Value)))
                CLDS_SetBlockAttr(fpB, pPrefs.t_fpid, p_dialog.tbFPID.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_cbid & "1", p_dialog.tbCable01.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_cbid & "2", p_dialog.tbCable02.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_cbid & "3", p_dialog.tbCable03.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_cbid & "4", p_dialog.tbCable04.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_cbid & "5", p_dialog.tbCable05.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_cbid & "6", p_dialog.tbCable06.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_cbid & "7", p_dialog.tbCable07.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_cbid & "8", p_dialog.tbCable08.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_cbid & "9", p_dialog.tbCable09.Text)
                CLDS_SetBlockAttr(fpB, pPrefs.t_cbid & "10", p_dialog.tbCable10.Text)
                CLDS_SetFPXRec(dTrans, fpB, p_dialog.tbProject.Text, p_dialog.tbPhase.Text)
                dTrans.Commit()
            End Using
        End Using
        Dim r As String = CLDS_SyncV9Faceplate(fpB, p_dialog.pBuilding)
        If r = "ERROR" Then
            Exit Sub
        End If
        If p_dialog.pMode = "UPDATE" And p_dialog.tbFPID.Text <> p_dialog.pFPID Then
            r = CLDS_DeleteV9Faceplate(p_dialog.pFPID)
            If r = "ERROR" Then
                Exit Sub
            End If
        End If
        CLDS_RangeTable(False)
        CLDS_SelectObject(fpBlock)
        fpBlock = Nothing
        'CLDS_CancelWP(p_dialog)
        CLDS_ExecuteQuery(p_dialog)
        Autodesk.AutoCAD.ApplicationServices.Application.UpdateScreen()
    End Sub
    Public Sub CLDS_CancelWP(ByVal p_dialog As RCMS_Container, Optional ByVal p_delete As Boolean = True)
        Dim doc As Document
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        If (p_dialog.pMode = "ADD" Or p_dialog.pMode = "QUERY") And p_delete Then
            If Not fpBlock.IsNull Then
                Using acLckDoc As DocumentLock = doc.LockDocument()
                    Using nTrans As Transaction = doc.TransactionManager.StartTransaction
                        Try
                            Dim fpB As BlockReference = TryCast(fpBlock.GetObject(OpenMode.ForWrite), BlockReference)
                            fpB.UpgradeOpen()
                            fpB.Erase()
                        Catch ex As Exception

                        End Try
                        nTrans.Commit()
                    End Using
                End Using
            End If
        End If
        If p_dialog.pMode = "UPDATE" Then
            CLDS_ShowWP(p_dialog, p_dialog.pFPID)
            fpBlock = ObjectId.Null
            p_dialog.pFPID = ""
            p_dialog.btSearch.Enabled = True
            p_dialog.btAddWP.Enabled = True
            p_dialog.btEditWP.Enabled = True
            p_dialog.btDeleteWP.Enabled = False
            p_dialog.btCancel.Enabled = False
            p_dialog.btSave.Enabled = False
            p_dialog.btAutofill.Enabled = False
            p_dialog.btRange.Enabled = True
            p_dialog.btZone.Enabled = True
            p_dialog.btList.Enabled = True
            p_dialog.btSync.Enabled = True
            p_dialog.btExcel.Enabled = True
            p_dialog.cxBuilding.Enabled = False
            p_dialog.cxFloor.Enabled = False
            p_dialog.cxRoom.Enabled = False
            p_dialog.cxModel.Enabled = False
            p_dialog.udFPNo.ReadOnly = True
            p_dialog.tbFPID.ReadOnly = True
            p_dialog.tbProject.ReadOnly = True
            p_dialog.tbPhase.ReadOnly = True
            CLDS_EnableCables(p_dialog, False)
        Else
            fpBlock = ObjectId.Null
            p_dialog.pFPID = ""
            p_dialog.btSearch.Enabled = True
            p_dialog.btAddWP.Enabled = True
            p_dialog.btEditWP.Enabled = False
            p_dialog.btCancel.Enabled = False
            p_dialog.btSave.Enabled = False
            p_dialog.btAutofill.Enabled = False
            p_dialog.btRange.Enabled = True
            p_dialog.btZone.Enabled = True
            p_dialog.btList.Enabled = True
            p_dialog.btSync.Enabled = True
            p_dialog.btExcel.Enabled = True
            p_dialog.cxBuilding.Enabled = False
            p_dialog.cxFloor.Enabled = False
            p_dialog.cxRoom.Enabled = False
            p_dialog.cxModel.Enabled = False
            p_dialog.udFPNo.ReadOnly = True
            p_dialog.tbFPID.ReadOnly = True
            p_dialog.tbProject.ReadOnly = True
            p_dialog.tbPhase.ReadOnly = True
            p_dialog.cxFloor.Text = p_dialog.pFloor
            p_dialog.cxRoom.Text = p_dialog.pRoom
            p_dialog.udFPNo.Value = 0
            p_dialog.tbFPID.Text = ""
            p_dialog.tbZone.Text = ""
            CLDS_ClearCables(p_dialog)
            CLDS_EnableCables(p_dialog, False)
        End If
    End Sub
#End Region
#Region "List-box functions"
    Public Function CLDS_PopulateCollection(ByVal p_context As String, ByVal p_require As String, ByVal p_column As String, Optional ByVal p_index As String = "", Optional ByVal p_id As String = "%") As Collection
        Dim c As Collection = Nothing
        Dim r As Integer = 0
        For j As Integer = 1 To 1000
            Dim arr As String(,)
            Dim acc As Collection
            Dim n As Integer = CLDS_Query(Nothing, j, p_context, p_require, p_id, arr, acc)
            If n <= 0 Then
                Exit For
            End If
            For i As Integer = 1 To n - 1
                If r = 0 Then
                    c = New Collection
                End If
                If p_index = "" Then
                    c.Add(arr(acc(p_require & "_" & p_column), i))
                Else
                    c.Add(arr(acc(p_require & "_" & p_column), i), arr(acc(p_require & "_" & p_index), i))
                End If
                r = r + 1
            Next
        Next
        Return c
    End Function
    Public Function CLDS_PopulateDictionary(ByVal p_context As String, ByVal p_require As String, ByVal p_column As String, Optional ByVal p_id As String = "%") As System.Collections.Generic.Dictionary(Of String, String())
        Dim c As System.Collections.Generic.Dictionary(Of String, String()) = Nothing
        Dim r As Integer = 0
        For j As Integer = 1 To 1000
            Dim arr As String(,)
            Dim acc As Collection
            Dim n As Integer = CLDS_Query(Nothing, j, p_context, p_require, p_id, arr, acc)
            If n <= 0 Then
                Exit For
            End If
            For i As Integer = 1 To n - 1
                If r = 0 Then
                    c = New System.Collections.Generic.Dictionary(Of String, String())
                End If
                Dim s(acc.Count) As String
                For x As Integer = 0 To acc.Count - 1
                    s(x) = arr(x, i)
                Next
                c.Add(arr(acc(p_require & "_" & p_column), i), s)
                r = r + 1
            Next
        Next
        Return c
    End Function
    Public Sub CLDS_PopulateCB(ByVal p_cb As System.Windows.Forms.ComboBox, ByVal p_coll As Collection, Optional ByVal p_default As String = "", Optional ByVal p_sep As String = "")
        If p_cb Is Nothing Then
            Exit Sub
        End If
        p_cb.Items.Clear()
        If p_default <> "" And p_sep = "" Then
            p_cb.Items.Add(p_default)
            p_cb.Text = p_default
        End If
        If p_coll Is Nothing Then
            Exit Sub
        End If
        For i As Integer = 1 To p_coll.Count
            Dim v As String = p_coll.Item(i)
            p_cb.Items.Add(v)
        Next
        If p_default = "" Or p_sep = "" Then
            Return
        End If

        For i As Integer = 0 To p_cb.Items.Count - 1
            Dim v As String = p_cb.Items(i)
            Dim ia() As String = Split(v, p_sep, -1, CompareMethod.Text)
            If ia(0) = p_default Then
                p_cb.SelectedItem = Nothing
                p_cb.Text = p_cb.Items(i)
                Exit Sub
            End If
        Next
    End Sub
    Public Sub CLDS_PopulateCB(ByVal p_cb As System.Windows.Forms.ComboBox, ByVal p_coll As System.Collections.Generic.Dictionary(Of String, String()), Optional ByVal p_default As String = "", Optional ByVal p_sep As String = "")
        If p_cb Is Nothing Then
            Exit Sub
        End If
        p_cb.Items.Clear()
        If p_default <> "" And p_sep = "" Then
            Dim cbi As New CLDS_ColourComboItem
            cbi.Text = p_default
            cbi.BColor = System.Drawing.Color.White
            cbi.FColor = System.Drawing.SystemColors.WindowText
            p_cb.Items.Add(cbi)
            p_cb.Text = p_default
        End If
        If p_coll Is Nothing Then
            Exit Sub
        End If
        Dim x As Integer
        x = 0
        For Each k As String In p_coll.Keys
            Dim cbi As New CLDS_ColourComboItem
            cbi.Text = k
            cbi.BColor = System.Drawing.Color.White
            cbi.FColor = System.Drawing.SystemColors.WindowText
            p_cb.Items.Add(cbi)
        Next
        If p_default = "" Or p_sep = "" Then
            Return
        End If

        For i As Integer = 0 To p_cb.Items.Count - 1
            Dim v As String = p_cb.Items(i)
            Dim ia() As String = Split(v, p_sep, -1, CompareMethod.Text)
            If ia(0) = p_default Then
                p_cb.SelectedItem = Nothing
                p_cb.Text = p_cb.Items(i)
                Exit Sub
            End If
        Next
    End Sub
    Public Sub CLDS_PopulateCB(ByVal p_cb As System.Windows.Forms.ComboBox, ByVal p_context As String, ByVal p_require As String, ByVal p_column As String)
        If p_cb Is Nothing Then
            Exit Sub
        End If
        p_cb.Items.Clear()
        For j As Integer = 1 To 1000
            Dim arr As String(,)
            Dim acc As Collection
            Dim n As Integer = CLDS_Query(Nothing, j, p_context, p_require, "%", arr, acc)
            If n <= 0 Then
                Exit For
            End If
            For i As Integer = 1 To n - 1
                p_cb.Items.Add(arr(acc(p_require & "_" & p_column), i))
            Next
        Next
    End Sub
    Public Sub CLDS_PopulateLB(ByVal p_lb As System.Windows.Forms.ListBox, ByVal p_context As String, ByVal p_require As String, ByVal p_column As String)
        If p_lb Is Nothing Then
            Exit Sub
        End If
        p_lb.Items.Clear()
        For j As Integer = 1 To 1000
            Dim arr As String(,)
            Dim acc As Collection
            Dim n As Integer = CLDS_Query(Nothing, j, p_context, p_require, "%", arr, acc)
            If n <= 0 Then
                Exit For
            End If
            For i As Integer = 1 To n - 1
                p_lb.Items.Add(arr(acc(p_require & "_" & p_column), i))
            Next
        Next
    End Sub
    Public Sub CLDS_GetFloors(ByVal p_dialog As RCMS_Container)
        Dim cFloor As Collection = CLDS_PopulateCollection("FACEPLATE", "FLOOR", "CODE", "", p_dialog.pBuilding)
        CLDS_PopulateCB(p_dialog.cxFloor, cFloor, p_dialog.pFloor, "~")
    End Sub
    Public Sub CLDS_GetRooms(ByVal p_dialog As RCMS_Container)
        Dim cRoom As Collection = CLDS_PopulateCollection("FACEPLATE", "ROOM", "CODE", "", p_dialog.pBuilding & ":" & p_dialog.pFloor)
        CLDS_PopulateCB(p_dialog.cxRoom, cRoom, p_dialog.pRoom, "~")
    End Sub
    Public Sub CLDS_RefreshLists(ByVal p_dialog As RCMS_Container)
        Dim cBldg As Collection = CLDS_PopulateCollection("FACEPLATE", "BUILDING", "BLDNG")
        CLDS_PopulateCB(p_dialog.cxBuilding, cBldg, p_dialog.pBuilding, ":")
        'Dim cWP As Collection = CLDS_PopulateCollection("FACEPLATE", "WALLPLATE", "ID")
        'CLDS_PopulateCB(p_dialog.cxModel, cWP, "-", "")
        dWP = CLDS_PopulateDictionary("FACEPLATE", "WALLPLATE", "ID")
        For Each k As String In dWP.Keys
            Dim s As String() = dWP(k)
            If s(1) = "0" And s(2) = "0" And s(3) = "0" And s(4) = "0" And s(5) = 0 Then
                s(6) = "N"
            Else
                s(6) = "Y"
            End If
        Next
        CLDS_PopulateCB(p_dialog.cxModel, dWP, "-", "")
    End Sub
#End Region
#Region "Table functions"
    Public Function CLDS_FindTable(ByVal nTrans As Transaction) As Table
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim psr As PromptSelectionResult = CLDS_SelectTables(nTrans, ed)
        Dim oid As ObjectId
        Dim obr As Table = Nothing
        If psr.Status = PromptStatus.OK Then
            Dim sobj() As ObjectId = psr.Value.GetObjectIds
            If sobj.GetLength(0) = 1 Then
                oid = sobj(0)
                obr = DirectCast(oid.GetObject(OpenMode.ForRead), Table)
            End If
        End If
        Return obr
    End Function

    Public Sub CLDS_RangeTable(Optional ByVal p_create As Boolean = True)
        Dim rarr As String(,)
        Dim racc As Collection
        Dim aarr As String(,)
        Dim aacc As Collection
        Dim i As Integer
        Dim j As Integer

        Dim name As String = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Name
        name = Path.GetFileNameWithoutExtension(name)

        'Dim pwidth = 4
        'Dim numRows As Integer = nr + na + 2
        'Dim numCols As Integer = 7
        'Dim rowHeight As Double = 3
        'Dim colWidth As Double = 3
        'Dim horMarg As Double = 1.5
        'Dim verMarg As Double = 0.8
        'Dim txtHeight As Double = 1


        Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Dim db As Database = doc.Database
        Dim ed As Editor = doc.Editor

        Dim xtb As Table = Nothing
        Dim ltb As String = ""
        Using docLock As DocumentLock = doc.LockDocument()
            Dim tr As Transaction = doc.TransactionManager.StartTransaction()
            Using tr
                xtb = CLDS_FindTable(tr)
                tr.Commit()
            End Using
        End Using
        Dim ptb As Point3d
        Dim ktb As Boolean = False
        If xtb Is Nothing Then
            If p_create Then
                If Not Autodesk.AutoCAD.Internal.Utils.IsInPaperSpace Then
                    'Using docLock As DocumentLock = doc.LockDocument()
                    'ed.SwitchToPaperSpace()
                    'End Using
                    MsgBox("Please switch to Paper Space before adding/updating RCMS number grid", MsgBoxStyle.Exclamation, "RCMS AutoCAD")
                    Exit Sub
                End If
                Dim pr As PromptPointResult = ed.GetPoint(vbLf & "Enter table insertion point: ")
                If pr.Status = PromptStatus.OK Then
                    ptb = pr.Value
                    ltb = pPrefs.l_grid
                    ktb = True
                End If
            End If
        Else
            ptb = xtb.Position
            ltb = xtb.Layer
            ktb = True
        End If
        If ktb Then
            Dim nr As Integer = CLDS_Query(Nothing, 1, "DRAWING", "RANGE", name, rarr, racc)
            If nr <= 0 Then
                MsgBox("ERROR: unable to get RCMS number ranges applicable to this drawing" & Chr(10) & CMERR, MsgBoxStyle.Critical, "RCMS")
                Exit Sub
            End If
            Dim na As Integer = CLDS_Query(Nothing, 1, "DRAWING", "AVAIL", name, aarr, aacc)
            If na <= 0 Then
                MsgBox("ERROR: unable to get RCMS number availability applicable to this drawing" & Chr(10) & CMERR, MsgBoxStyle.Critical, "RCMS")
                Exit Sub
            End If
            Dim numRows As Integer = nr + na + 2
            Dim numCols As Integer = 7
            Dim pwidth = pPrefs.w_grid
            Dim rowHeight As Double = pPrefs.h_grid
            Dim colWidth As Double = pPrefs.c_grid
            Dim horMarg As Double = pPrefs.m_grid
            Dim verMarg As Double = pPrefs.v_grid
            Dim txtHeight As Double = pPrefs.t_grid
            Dim tb As New Table()
            tb.TableStyle = db.Tablestyle
            tb.Rows(0).Height = rowHeight
            tb.Columns(0).Width = colWidth

            ' Add the remaining rows and columns

            tb.InsertRows(1, rowHeight, numRows - 1)
            tb.InsertColumns(1, colWidth, numCols - 1)

            ' To query the number of rows and columns...
            '
            ' int nRows = tb.Rows.Count;
            ' int nCols = tb.Columns.Count;

            ' To "suppress" the title and header, find the row
            ' with a style of "Title" or "Header" and set it to ""

            'tb.Cells(0, -1).Style = "Title"
            'tb.Cells(1, -1).Style = "Header"
            tb.Cells(0, -1).Style = ""
            tb.Cells(1, -1).Style = ""

            ' Add the contents of the Title cell

            'Dim tc As Cell = tb.Cells(0, 0)

            'tc.Contents.Add()
            'tc.Contents(0).TextHeight = txtHeight
            'tc.Contents(0).TextString = ""

            'tb.SetRowHeight(3)
            'tb.SetColumnWidth(15)
            tb.SetRowHeight(rowHeight)
            tb.SetColumnWidth(colWidth)
            tb.Position = ptb
            tb.Layer = ltb
            tb.Color = Color.FromColorIndex(ColorMethod.ByLayer, 256)

            ' Create a 2-dimensional array
            ' of our table contents
            Dim str As String(,) = New String((nr + na + 2), 7) {}

            str(0, 0) = rarr(racc("RANGE_DRAWING"), 1)
            str(0, 1) = ""
            str(0, 2) = "RANGE"
            str(0, 3) = ""
            str(0, 4) = ""
            str(0, 5) = ""
            str(0, 6) = ""
            str(1, 0) = ""
            str(1, 1) = ""
            str(1, 2) = "Voice"
            str(1, 3) = "Data"
            str(1, 4) = "Coax"
            str(1, 5) = "Audio"
            str(1, 6) = "Fiber"
            For i = 1 To nr - 1
                str(1 + i, 0) = rarr(racc("RANGE_ZONE"), i)
                str(1 + i, 1) = rarr(racc("RANGE_CLOSET"), i)
                str(1 + i, 2) = " " & rarr(racc("RANGE_VOICE_F"), i) & " thru " + Chr(10) + " " & rarr(racc("RANGE_VOICE_T"), i)
                str(1 + i, 3) = " " & rarr(racc("RANGE_DATA_F"), i) & " thru " + Chr(10) + " " & rarr(racc("RANGE_DATA_T"), i)
                str(1 + i, 4) = " " & rarr(racc("RANGE_COAX_F"), i) & " thru " + Chr(10) + " " & rarr(racc("RANGE_COAX_T"), i)
                str(1 + i, 5) = " " & rarr(racc("RANGE_AUDIO_F"), i) & " thru " + Chr(10) + " " & rarr(racc("RANGE_AUDIO_T"), i)
                str(1 + i, 6) = " " & rarr(racc("RANGE_FIBER_F"), i) & " thru " + Chr(10) + " " & rarr(racc("RANGE_FIBER_T"), i)
            Next i
            str(1 + nr, 0) = "ER"
            str(1 + nr, 1) = ""
            str(1 + nr, 2) = "Next Number"
            str(1 + nr, 3) = ""
            str(1 + nr, 4) = ""
            str(1 + nr, 5) = ""
            str(1 + nr, 6) = ""
            str(2 + nr, 0) = ""
            str(2 + nr, 1) = ""
            str(2 + nr, 2) = "Voice"
            str(2 + nr, 3) = "Data"
            str(2 + nr, 4) = "Coax"
            str(2 + nr, 5) = "Audio"
            str(2 + nr, 6) = "Fiber"
            For j = 1 To na - 1
                str(2 + nr + j, 0) = aarr(aacc("AVAIL_ZONE"), j)
                str(2 + nr + j, 1) = aarr(aacc("AVAIL_CLOSET"), j)
                str(2 + nr + j, 2) = " " & Replace(aarr(aacc("AVAIL_VOICE"), j), "thru ", "thru " & Chr(10) & " ")
                str(2 + nr + j, 3) = " " & Replace(aarr(aacc("AVAIL_DATA"), j), "thru ", "thru " & Chr(10) & " ")
                str(2 + nr + j, 4) = " " & Replace(aarr(aacc("AVAIL_COAX"), j), "thru ", "thru " & Chr(10) & " ")
                str(2 + nr + j, 5) = " " & Replace(aarr(aacc("AVAIL_AUDIO"), j), "thru ", "thru " & Chr(10) & " ")
                str(2 + nr + j, 6) = " " & Replace(aarr(aacc("AVAIL_FIBER"), j), "thru ", "thru " & Chr(10) & " ")
            Next j

            ' Use a nested loop to add and format each cell
            For i = 0 To numRows - 1
                For j = 0 To numCols - 1
                    tb.Cells(i, j).TextHeight = txtHeight
                    If (i = 0 Or i = (nr + 1)) Then
                        tb.Cells(i, j).TextHeight = txtHeight * 2
                    ElseIf (i = 1 Or i = (nr + 2)) Then
                        tb.Cells(i, j).TextHeight = txtHeight * 1.5
                    End If
                    tb.Cells(i, j).TextString = str(i, j)
                    If ((i > 1 And i <= nr) Or (i > nr + 2 And i <= nr + na + 1)) And (j > 1) Then
                        tb.Cells(i, j).Alignment = CellAlignment.MiddleLeft
                    Else
                        tb.Cells(i, j).Alignment = CellAlignment.MiddleCenter
                    End If
                    tb.Cells(i, j).Borders.Left.Margin = horMarg
                    tb.Cells(i, j).Borders.Right.Margin = horMarg
                    tb.Cells(i, j).Borders.Top.Margin = verMarg
                    tb.Cells(i, j).Borders.Bottom.Margin = verMarg
                Next
            Next
            Dim rng1 As CellRange = CellRange.Create(tb, 0, 0, 1, 1)
            tb.MergeCells(rng1)
            Dim rng2 As CellRange = CellRange.Create(tb, 0, 2, 0, 6)
            tb.MergeCells(rng2)
            Dim rng3 As CellRange = CellRange.Create(tb, nr + 1, 0, nr + 2, 1)
            tb.MergeCells(rng3)
            Dim rng4 As CellRange = CellRange.Create(tb, nr + 1, 2, nr + 1, 6)
            tb.MergeCells(rng4)
            tb.GenerateLayout()
            Dim tw As Double = tb.Width
            Dim ts As Double = pwidth / tw
            tb.TransformBy(Matrix3d.Scaling(ts, ptb))

            Using docLock As DocumentLock = doc.LockDocument()
                Dim tr As Transaction = doc.TransactionManager.StartTransaction()
                Using tr
                    CLDS_SetGridXData(tr, tb, "RCMS Grid")
                    Dim bt As BlockTable = DirectCast(tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead), BlockTable)
                    ' Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)
                    Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(BlockTableRecord.PaperSpace), OpenMode.ForWrite), BlockTableRecord)
                    btr.AppendEntity(tb)
                    tr.AddNewlyCreatedDBObject(tb, True)
                    If Not xtb Is Nothing Then
                        Dim fpB As Table = TryCast(tr.GetObject(xtb.ObjectId, OpenMode.ForWrite, False), Table)
                        fpB.UpgradeOpen()
                        fpB.Erase()
                    End If
                    tr.Commit()
                End Using
            End Using
        End If
    End Sub

#End Region
#Region "Excel reports"
    Public Sub CLDS_Excel_FPList(ByVal p_lv As System.Windows.Forms.ListView, ByVal p_building As String, Optional ByVal p_floor As String = "")
        Dim name As String = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Name
        name = Path.GetFileNameWithoutExtension(name)
        Dim fname As String
        If p_lv Is Nothing Then
            fname = System.Environment.ExpandEnvironmentVariables(pPrefs.p_excl) & "\rcms_" & p_building & "_fp.xlsx"
        Else
            fname = System.Environment.ExpandEnvironmentVariables(pPrefs.p_excl) & "\rcms_" & name & "_fp.xlsx"
        End If
        If File.Exists(fname) Then
            File.Delete(fname)
        End If
        Dim finfo As FileInfo = New FileInfo(fname)
        Dim v_building As String = pRCMSDialog.tbBuilding.Text
        Dim xlPackage As New ExcelPackage(finfo)
        Using xlPackage
            Dim xlWorksheet As ExcelWorksheet = xlPackage.Workbook.Worksheets.Add(p_building & " FP")
            Dim row As Integer = 1
            Dim hrow As Integer = 0
            Dim fcol As Integer = 7
            xlWorksheet.Cells(row, 1).Value = "Building " & v_building
            Using r As ExcelRange = xlWorksheet.Cells(row, 1, row, pPrefs.x_cbno + fcol)
                'r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Britannic Bold", 22, System.Drawing.FontStyle.Italic))
                r.Style.Font.Color.SetColor(System.Drawing.Color.White)
                'r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.CenterContinuous
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
                r.Style.Fill.BackgroundColor.SetColor(pPrefs.c_texc)
            End Using
            If Not p_lv Is Nothing Then
                row += 1
                xlWorksheet.Cells(row, 1).Value = "Drawing " & name
                Using r As ExcelRange = xlWorksheet.Cells(row, 1, row, pPrefs.x_cbno + fcol)
                    'r.Merge = True
                    r.Style.Font.SetFromFont(New System.Drawing.Font("Britannic Bold", 22, System.Drawing.FontStyle.Italic))
                    r.Style.Font.Color.SetColor(System.Drawing.Color.White)
                    'r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.CenterContinuous
                    r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                    r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
                    r.Style.Fill.BackgroundColor.SetColor(pPrefs.c_texc)
                End Using
            End If
            row += 1
            xlWorksheet.Cells(row, 1).Value = "FP List"
            Using r As ExcelRange = xlWorksheet.Cells(row, 1, row, pPrefs.x_cbno + fcol)
                'r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Britannic Bold", 18, System.Drawing.FontStyle.Italic))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                'r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.CenterContinuous
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
                r.Style.Fill.BackgroundColor.SetColor(pPrefs.c_hexc)
            End Using
            row += 2
            hrow = row
            xlWorksheet.Cells(row, 1).Value = "FP ID"
            xlWorksheet.Cells(row, 2).Value = "Floor"
            xlWorksheet.Cells(row, 3).Value = "Room"
            xlWorksheet.Cells(row, 4).Value = "No"
            xlWorksheet.Cells(row, 5).Value = "Model"
            xlWorksheet.Cells(row, 6).Value = "Project"
            xlWorksheet.Cells(row, 7).Value = "Phase"
            For c As Integer = 1 To pPrefs.x_cbno
                xlWorksheet.Cells(row, c + fcol).Value = "CBID#" & Trim(Str$(c))
            Next
            xlWorksheet.Cells(row, 1, row, pPrefs.x_cbno + fcol).Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
            xlWorksheet.Cells(row, 1, row, pPrefs.x_cbno + fcol).Style.Fill.BackgroundColor.SetColor(pPrefs.c_hexc)
            xlWorksheet.Cells(row, 1, row, pPrefs.x_cbno + fcol).Style.Font.Bold = True

            If p_lv Is Nothing Then
                Dim r As Integer = 0
                For j As Integer = 1 To 1000
                    Dim arr As String(,)
                    Dim acc As Collection
                    Dim p_id As String = "BUILDING=""" & p_building & """"
                    If p_floor <> "" Then p_id = p_id & " FLOOR=""" & p_floor & """"
                    If pRCMSDialog.cxFilterProject.Text <> "" Then p_id = p_id & " PROJECT=""" & pRCMSDialog.cxFilterProject.Text & """"
                    If pRCMSDialog.cxFilterPhase.Text <> "" Then p_id = p_id & " PHASE=""" & pRCMSDialog.cxFilterPhase.Text & """"
                    Dim n As Integer = CLDS_Query(Nothing, j, "EXCEL", "FPLIST", p_id, arr, acc)
                    If n <= 0 Then
                        Exit For
                    End If
                    For i As Integer = 1 To n - 1
                        Dim fpID As String = arr(acc("FPLIST_FPID"), i)
                        Dim room As String = arr(acc("FPLIST_ROOMID"), i)
                        Dim flor As String = arr(acc("FPLIST_BFLOOR"), i)
                        Dim fpno As String = arr(acc("FPLIST_FPNO"), i)
                        Dim wpID As String = arr(acc("FPLIST_MODEL"), i)
                        Dim fpproj As String = arr(acc("FPLIST_PROJECT"), i)
                        Dim fpphase As String = arr(acc("FPLIST_PHASE"), i)
                        row += 1
                        xlWorksheet.Cells(row, 1).Value = fpID
                        xlWorksheet.Cells(row, 2).Value = flor
                        xlWorksheet.Cells(row, 3).Value = room
                        xlWorksheet.Cells(row, 4).Value = fpno
                        xlWorksheet.Cells(row, 5).Value = wpID
                        xlWorksheet.Cells(row, 6).Value = fpproj
                        xlWorksheet.Cells(row, 7).Value = fpphase
                        For k = 1 To pPrefs.x_cbno
                            Dim m As String = Trim(Str$(k))
                            Dim c As String = arr(acc("FPLIST_CBID" & m), i)
                            xlWorksheet.Cells(row, fcol + k).Value = c
                        Next
                    Next
                Next
            Else
                Dim doc As Document
                doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
                Using acLckDoc As DocumentLock = doc.LockDocument()
                    Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                        For Each lvi As System.Windows.Forms.ListViewItem In p_lv.Items
                            Dim fpID As String = lvi.Text
                            Dim room As String = lvi.SubItems(2).Text
                            Dim flor As String = lvi.SubItems(1).Text
                            Dim fpno As String = lvi.SubItems(7).Text
                            Dim wpID As String = lvi.SubItems(3).Text
                            Dim fpproj As String = lvi.SubItems(5).Text
                            Dim fpphase As String = lvi.SubItems(6).Text
                            Dim wpH As New Handle(Val(lvi.SubItems(8).Text))
                            Dim wpO As ObjectId = doc.Database.GetObjectId(False, wpH, 0)
                            Dim wpE As BlockReference = TryCast(dTrans.GetObject(wpO, OpenMode.ForRead), BlockReference)
                            If Not wpE Is Nothing Then
                                If (pRCMSDialog.cxFilterProject.Text = "" Or fpproj = pRCMSDialog.cxFilterProject.Text) And (pRCMSDialog.cxFilterPhase.Text = "" Or fpphase = pRCMSDialog.cxFilterPhase.Text) Then
                                    row += 1
                                    xlWorksheet.Cells(row, 1).Value = fpID
                                    xlWorksheet.Cells(row, 2).Value = flor
                                    xlWorksheet.Cells(row, 3).Value = room
                                    xlWorksheet.Cells(row, 4).Value = fpno
                                    xlWorksheet.Cells(row, 5).Value = wpID
                                    xlWorksheet.Cells(row, 6).Value = fpproj
                                    xlWorksheet.Cells(row, 7).Value = fpphase
                                    For i = 1 To pPrefs.x_cbno
                                        Dim n As String = Trim(Str$(i))
                                        Dim c As String = CLDS_GetBlockAttr(wpE, pPrefs.t_cbid & n)
                                        xlWorksheet.Cells(row, fcol + i).Value = c
                                    Next
                                End If
                            End If
                        Next
                        dTrans.Commit()
                    End Using
                End Using
            End If
            xlWorksheet.Cells(hrow, 1, row, pPrefs.x_cbno + fcol).AutoFitColumns()
            xlWorksheet.Cells(hrow, 1, hrow, pPrefs.x_cbno + fcol).AutoFilter = True
            If p_lv Is Nothing Then
                If p_floor = "" Then
                    xlPackage.Workbook.Properties.Title = "RCMS FP List for building " & v_building
                Else
                    xlPackage.Workbook.Properties.Title = "RCMS FP List for building " & v_building & ", floor " & p_floor
                    xlPackage.Workbook.Properties.SetCustomPropertyValue("RCMS Floor", p_floor)
                End If
            Else
                xlPackage.Workbook.Properties.Title = "RCMS FP List for AutoCAD drawing " & name
                xlPackage.Workbook.Properties.SetCustomPropertyValue("AutoCAD drawing", name)
            End If
            xlPackage.Workbook.Properties.SetCustomPropertyValue("RCMS Building", v_building)
            xlPackage.Workbook.Properties.SetCustomPropertyValue("RCMS AutoCAD Version", v_no & " " & v_date)
            xlPackage.Save()
        End Using
        MsgBox("Created spreadsheet file " & fname, MsgBoxStyle.Information, "RCMS AutoCAD")
    End Sub
    Public Function RCMS_CableType(ByVal p_cabid As String) As String
        If p_cabid = "D" Then
            Return "DATA"
        ElseIf p_cabid = "V" Then
            Return "VOICE"
        ElseIf p_cabid = "A" Then
            Return "AUDIO"
        ElseIf p_cabid = "C" Then
            Return "COAX"
        ElseIf p_cabid = "F" Then
            Return "FIBER"
        End If
        Return "DATA"
    End Function
    Public Sub CLDS_Excel_Count(ByVal p_lv As System.Windows.Forms.ListView, ByVal p_building As String, Optional ByVal p_floor As String = "")
        Dim name As String = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Name
        name = Path.GetFileNameWithoutExtension(name)
        Dim fname As String
        If p_lv Is Nothing Then
            fname = System.Environment.ExpandEnvironmentVariables(pPrefs.p_excl) & "\rcms_" & p_building & "_count.xlsx"
        Else
            fname = System.Environment.ExpandEnvironmentVariables(pPrefs.p_excl) & "\rcms_" & name & "_count.xlsx"
        End If
        If File.Exists(fname) Then
            File.Delete(fname)
        End If
        Dim finfo As FileInfo = New FileInfo(fname)
        Dim v_building As String = pRCMSDialog.tbBuilding.Text
        Dim xlPackage As New ExcelPackage(finfo)
        Using xlPackage
            Dim xlWorksheet As ExcelWorksheet = xlPackage.Workbook.Worksheets.Add("WP Count")
            xlWorksheet.PrinterSettings.Orientation = eOrientation.Portrait
            Dim xlh As ExcelHeaderFooter = xlWorksheet.HeaderFooter
            xlh.FirstHeader.CenteredText = "&U&12&""Arial,Bold""WP COUNT REPORT"

            Dim srow As Integer = 1     ' Start row
            Dim hrow As Integer = 0     ' Header row number
            Dim mrow As Integer = 48    ' Expected maximum rows per sheet
            Dim fcol As Integer = 0     ' Number of floor columns, including total
            Dim mcol As Integer = 14    ' Expected maximum column
            Dim trow As Integer = 0     ' Title block row start
            Dim tcol1 As Integer = 1    ' Title block left column start
            Dim tcol2 As Integer = 3    ' Title block left column end
            Dim tcol3 As Integer = 4    ' Title block right column start
            Dim tcol4 As Integer = mcol ' Title block right column end

            Dim row As Integer = srow   ' Current row pointer

            Dim x As String
            If p_lv Is Nothing Then
                x = "This WP Count Report is based on the WP Model Number located within the Smart Blocks of the CAD drawings."
                x = x & " The cable counts for Data, Voice, Coax, Audio and Fiber are calculated from the WP Schedule and not"
                x = x & " the actual appearance of a cable number on the CAD drawings."
            Else
                x = "This WP Count Report is based on the WP Model Number located within the Smart Blocks of the named CAD drawing."
                x = x & " The cable counts for Data, Voice, Coax, Audio and Fiber are calculated from the appearance of a cable number " & _
                "on the CAD drawing."
            End If
            xlWorksheet.Cells(row, 1).Value = x
            Using r As ExcelRange = xlWorksheet.Cells(row, 1, row + 2, mcol)
                r.Merge = True
                r.Style.WrapText = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 8, System.Drawing.FontStyle.Regular))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center
                r.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Top
            End Using
            row += 4
            trow = row
            xlWorksheet.Cells(row, tcol1).Value = "Name"
            Using r As ExcelRange = xlWorksheet.Cells(row, tcol1, row, tcol2)
                r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Bold))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                'r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.CenterContinuous
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
                r.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.FromArgb(192, 192, 192))
            End Using
            xlWorksheet.Cells(row, tcol3).Value = "Input Column"
            Using r As ExcelRange = xlWorksheet.Cells(row, tcol3, row, tcol4)
                r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Bold))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                'r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.CenterContinuous
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
                r.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.FromArgb(192, 192, 192))
            End Using
            row += 1
            xlWorksheet.Cells(row, tcol1).Value = "Campus"
            Using r As ExcelRange = xlWorksheet.Cells(row, tcol1, row, tcol2)
                r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
            End Using
            xlWorksheet.Cells(row, tcol3).Value = pRCMSDialog.pCampus
            Using r As ExcelRange = xlWorksheet.Cells(row, tcol3, row, tcol4)
                r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center
                r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
            End Using
            row += 1
            xlWorksheet.Cells(row, tcol1).Value = "Building Name"
            Using r As ExcelRange = xlWorksheet.Cells(row, tcol1, row, tcol2)
                r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
            End Using
            xlWorksheet.Cells(row, tcol3).Value = Mid$(pRCMSDialog.tbBuilding.Text, InStr(pRCMSDialog.tbBuilding.Text, ": ") + 2)
            Using r As ExcelRange = xlWorksheet.Cells(row, tcol3, row, tcol4)
                r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center
                r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
            End Using
            row += 1
            xlWorksheet.Cells(row, tcol1).Value = "Building Number"
            Using r As ExcelRange = xlWorksheet.Cells(row, tcol1, row, tcol2)
                r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
            End Using
            xlWorksheet.Cells(row, tcol3).Value = p_building
            Using r As ExcelRange = xlWorksheet.Cells(row, tcol3, row, tcol4)
                r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center
                r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
            End Using
            If Not p_lv Is Nothing Then
                row += 1
                xlWorksheet.Cells(row, tcol1).Value = "Drawing Name"
                Using r As ExcelRange = xlWorksheet.Cells(row, tcol1, row, tcol2)
                    r.Merge = True
                    r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                    r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                    r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                    r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
                End Using
                xlWorksheet.Cells(row, tcol3).Value = name
                Using r As ExcelRange = xlWorksheet.Cells(row, tcol3, row, tcol4)
                    r.Merge = True
                    r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                    r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                    r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center
                    r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
                End Using
            End If
            If pRCMSDialog.cxFilterProject.Text <> "" Then
                row += 1
                xlWorksheet.Cells(row, tcol1).Value = "Project"
                Using r As ExcelRange = xlWorksheet.Cells(row, tcol1, row, tcol2)
                    r.Merge = True
                    r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                    r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                    r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                    r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
                End Using
                xlWorksheet.Cells(row, tcol3).Value = pRCMSDialog.cxFilterProject.Text
                Using r As ExcelRange = xlWorksheet.Cells(row, tcol3, row, tcol4)
                    r.Merge = True
                    r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                    r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                    r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center
                    r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
                End Using
            End If
            If pRCMSDialog.cxFilterPhase.Text <> "" Then
                row += 1
                xlWorksheet.Cells(row, tcol1).Value = "Phase"
                Using r As ExcelRange = xlWorksheet.Cells(row, tcol1, row, tcol2)
                    r.Merge = True
                    r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                    r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                    r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                    r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
                End Using
                xlWorksheet.Cells(row, tcol3).Value = pRCMSDialog.cxFilterPhase.Text
                Using r As ExcelRange = xlWorksheet.Cells(row, tcol3, row, tcol4)
                    r.Merge = True
                    r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                    r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                    r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center
                    r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
                End Using
            End If
            row += 1
            xlWorksheet.Cells(row, tcol1).Value = "RUN Date"
            Using r As ExcelRange = xlWorksheet.Cells(row, tcol1, row, tcol2)
                r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
            End Using
            Dim now As Date = Date.Now
            xlWorksheet.Cells(row, tcol3).Value = now.ToString("dd-MMM-yyyy")
            Using r As ExcelRange = xlWorksheet.Cells(row, tcol3, row, tcol4)
                r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center
                r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
            End Using
            Using r As ExcelRange = xlWorksheet.Cells(trow, tcol1, trow, tcol4)
                r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Double)
            End Using
            Using r As ExcelRange = xlWorksheet.Cells(trow + 1, tcol1, row, tcol4)
                r.Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thick)
            End Using
            'Dim x As String = "This WP Count Report is based on the WP Model Number located within the Smart Blocks of the CAD drawings."
            'If p_lv Is Nothing Then
            'x = x & " The cable counts for Data, Voice, Coax, Audio and Fiber are calculated from the WP Schedule and not the actual appearance of a cable number " & _
            '"on the CAD drawings"
            'End If
            'xlWorksheet.Cells(3, 11).Value = x
            'Using r As ExcelRange = xlWorksheet.Cells(3, 11, row, mcol)
            'r.Merge = True
            'r.Style.WrapText = True
            'r.Style.Font.SetFromFont(New System.Drawing.Font("Arial", 8, System.Drawing.FontStyle.Regular))
            'r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
            'r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
            'r.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Top
            'End Using
            x = "To Print Reports longer than one sheet." & Chr(10) & "Make sure you are on Sheet ""WP Count""," & Chr(10) & "on Tool Bar click View," & Chr(10) & "Select Page Break Preview. " & _
            Chr(10) & "Drag lower edge of blue outline" & Chr(10) & "down to bottom of line 84." & Chr(10) & "Press Print."
            Dim xc As ExcelComment = xlWorksheet.Cells(trow, mcol + 4).AddComment(x, "RCMS AutoCAD")
            xc.BackgroundColor = System.Drawing.Color.PaleGoldenrod
            xc.HorizontalAlignment = Drawing.Vml.eTextAlignHorizontalVml.Left
            xc.VerticalAlignment = Drawing.Vml.eTextAlignVerticalVml.Top
            xc.Visible = True
            xc.AutoFit = True
            row += 2
            xlWorksheet.Cells(row, 2).Value = "PP = Patch Panel : Data / 48 = Total Switches"
            xlWorksheet.Cells(row, 2).Style.Font.SetFromFont(New System.Drawing.Font("Arial", 10, System.Drawing.FontStyle.Bold))
            row += 1
            xlWorksheet.Cells(row, 2).Value = "RISER = Suggested Voice Riser Size : Voice X 4 X 1.25"
            xlWorksheet.Cells(row, 2).Style.Font.SetFromFont(New System.Drawing.Font("Arial", 10, System.Drawing.FontStyle.Bold))
            row += 1
            xlWorksheet.Cells(row, 1).Value = "q"
            xlWorksheet.Cells(row, 1).Style.Font.SetFromFont(New System.Drawing.Font("Wingdings 3", 12, System.Drawing.FontStyle.Regular))

            Dim fs As New RCMS_FloorSorter()
            Dim matrix As New SortedDictionary(Of String, System.Collections.Generic.SortedDictionary(Of String, Integer))(New RCMS_WPListSorter)
            matrix.Add("DATA", New System.Collections.Generic.SortedDictionary(Of String, Integer)(fs))
            matrix("DATA").Add("TOTAL", 0)
            matrix.Add("PP", New System.Collections.Generic.SortedDictionary(Of String, Integer)(fs))
            matrix("PP").Add("TOTAL", 0)
            matrix.Add("VOICE", New System.Collections.Generic.SortedDictionary(Of String, Integer)(fs))
            matrix("VOICE").Add("TOTAL", 0)
            matrix.Add("RISER", New System.Collections.Generic.SortedDictionary(Of String, Integer)(fs))
            matrix("RISER").Add("TOTAL", 0)
            matrix.Add("AUDIO", New System.Collections.Generic.SortedDictionary(Of String, Integer)(fs))
            matrix("AUDIO").Add("TOTAL", 0)
            matrix.Add("COAX", New System.Collections.Generic.SortedDictionary(Of String, Integer)(fs))
            matrix("COAX").Add("TOTAL", 0)
            matrix.Add("FIBER", New System.Collections.Generic.SortedDictionary(Of String, Integer)(fs))
            matrix("FIBER").Add("TOTAL", 0)
            If p_lv Is Nothing Then
                Dim r As Integer = 0
                For j As Integer = 1 To 1000
                    Dim arr As String(,)
                    Dim acc As Collection
                    Dim p_id As String = "BUILDING=""" & p_building & """"
                    If p_floor <> "" Then p_id = p_id & " FLOOR=""" & p_floor & """"
                    If pRCMSDialog.cxFilterProject.Text <> "" Then p_id = p_id & " PROJECT=""" & pRCMSDialog.cxFilterProject.Text & """"
                    If pRCMSDialog.cxFilterPhase.Text <> "" Then p_id = p_id & " PHASE=""" & pRCMSDialog.cxFilterPhase.Text & """"
                    Dim n As Integer = CLDS_Query(Nothing, j, "EXCEL", "FPLIST", p_id, arr, acc)
                    If n <= 0 Then
                        Exit For
                    End If
                    For i As Integer = 1 To n - 1
                        Dim fpID As String = arr(acc("FPLIST_FPID"), i)
                        Dim room As String = arr(acc("FPLIST_ROOMID"), i)
                        Dim flor As String = arr(acc("FPLIST_BFLOOR"), i)
                        Dim fpno As String = arr(acc("FPLIST_FPNO"), i)
                        Dim wpID As String = arr(acc("FPLIST_MODEL"), i)
                        Dim fpproj As String = arr(acc("FPLIST_PROJECT"), i)
                        Dim fpphase As String = arr(acc("FPLIST_PHASE"), i)
                        If Not matrix.ContainsKey(wpID) Then
                            matrix.Add(wpID, New System.Collections.Generic.SortedDictionary(Of String, Integer)(fs))
                            For Each item As KeyValuePair(Of String, Integer) In matrix("DATA")
                                matrix(wpID).Add(item.Key, 0)
                            Next
                        End If
                        If Not matrix("DATA").ContainsKey(flor) Then
                            For Each item As KeyValuePair(Of String, System.Collections.Generic.SortedDictionary(Of String, Integer)) In matrix
                                item.Value.Add(flor, 0)
                            Next
                        End If
                        matrix(wpID)("TOTAL") = matrix(wpID)("TOTAL") + 1
                        matrix(wpID)(flor) = matrix(wpID)(flor) + 1
                        For k = 1 To pPrefs.x_cbno
                            Dim m As String = Trim(Str$(k))
                            Dim c As String = arr(acc("FPLIST_CBID" & m), i)
                            If c <> "" Then
                                Dim t As String = RCMS_CableType(Mid$(c, Len(c), 1))
                                matrix(t)("TOTAL") = matrix(t)("TOTAL") + 1
                                matrix(t)(flor) = matrix(t)(flor) + 1
                                If t = "DATA" Then
                                    matrix("PP")("TOTAL") = Math.Floor((matrix("DATA")("TOTAL") + 47) / 48)
                                    matrix("PP")(flor) = Math.Floor((matrix("DATA")(flor) + 47) / 48)
                                End If
                                If t = "VOICE" Then
                                    matrix("RISER")("TOTAL") = Math.Floor((matrix("VOICE")("TOTAL") * 4) * 1.25)
                                    matrix("RISER")(flor) = Math.Floor((matrix("VOICE")(flor) * 4) * 1.25)
                                End If
                            End If
                        Next
                    Next
                Next
            Else
                Dim doc As Document
                doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
                Using acLckDoc As DocumentLock = doc.LockDocument()
                    Using dTrans As Transaction = doc.TransactionManager.StartTransaction
                        For Each lvi As System.Windows.Forms.ListViewItem In p_lv.Items
                            Dim fpID As String = lvi.Text
                            Dim room As String = lvi.SubItems(2).Text
                            Dim flor As String = lvi.SubItems(1).Text
                            Dim fpno As String = lvi.SubItems(7).Text
                            Dim wpID As String = lvi.SubItems(3).Text
                            Dim fpproj As String = lvi.SubItems(5).Text
                            Dim fpphase As String = lvi.SubItems(6).Text
                            Dim wpH As New Handle(Val(lvi.SubItems(8).Text))
                            Dim wpO As ObjectId = doc.Database.GetObjectId(False, wpH, 0)
                            Dim wpE As BlockReference = TryCast(dTrans.GetObject(wpO, OpenMode.ForRead), BlockReference)
                            If Not wpE Is Nothing Then
                                If (pRCMSDialog.cxFilterProject.Text = "" Or fpproj = pRCMSDialog.cxFilterProject.Text) And (pRCMSDialog.cxFilterPhase.Text = "" Or fpphase = pRCMSDialog.cxFilterPhase.Text) Then
                                    If Not matrix.ContainsKey(wpID) Then
                                        matrix.Add(wpID, New System.Collections.Generic.SortedDictionary(Of String, Integer)(fs))
                                        For Each item As KeyValuePair(Of String, Integer) In matrix("DATA")
                                            matrix(wpID).Add(item.Key, 0)
                                        Next
                                    End If
                                    If Not matrix("DATA").ContainsKey(flor) Then
                                        For Each item As KeyValuePair(Of String, System.Collections.Generic.SortedDictionary(Of String, Integer)) In matrix
                                            item.Value.Add(flor, 0)
                                        Next
                                    End If
                                    matrix(wpID)("TOTAL") = matrix(wpID)("TOTAL") + 1
                                    matrix(wpID)(flor) = matrix(wpID)(flor) + 1
                                    For i = 1 To pPrefs.x_cbno
                                        Dim n As String = Trim(Str$(i))
                                        Dim c As String = CLDS_GetBlockAttr(wpE, pPrefs.t_cbid & n)
                                        If c <> "" Then
                                            Dim t As String = RCMS_CableType(Mid$(c, Len(c), 1))
                                            matrix(t)("TOTAL") = matrix(t)("TOTAL") + 1
                                            matrix(t)(flor) = matrix(t)(flor) + 1
                                            If t = "DATA" Then
                                                'matrix("PP")("TOTAL") = Math.Floor((matrix("DATA")("TOTAL") + 47) / 48)
                                                matrix("PP")(flor) = Math.Floor((matrix("DATA")(flor) + 47) / 48)
                                            End If
                                            If t = "VOICE" Then
                                                'matrix("RISER")("TOTAL") = Math.Floor((matrix("VOICE")("TOTAL") * 4) * 1.25)
                                                matrix("RISER")(flor) = Math.Floor((matrix("VOICE")(flor) * 4) * 1.25)
                                            End If
                                        End If
                                    Next
                                End If
                            End If
                        Next
                        dTrans.Commit()
                    End Using
                End Using
            End If

            Dim ppt As Integer = 0
            For Each item As KeyValuePair(Of String, Integer) In matrix("PP")
                If item.Key <> "TOTAL" Then
                    ppt += item.Value
                End If
            Next
            matrix("PP")("TOTAL") = ppt

            Dim rst As Integer = 0
            For Each item As KeyValuePair(Of String, Integer) In matrix("RISER")
                If item.Key <> "TOTAL" Then
                    rst += item.Value
                End If
            Next
            matrix("RISER")("TOTAL") = rst

            row += 1
            hrow = row
            xlWorksheet.Cells(row, 1).Value = "WP"
            xlWorksheet.Cells(row, 1).Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
            fcol = 1

            For Each item As KeyValuePair(Of String, Integer) In matrix("DATA")
                fcol = fcol + 1
                xlWorksheet.Cells(row, fcol).Value = item.Key
                xlWorksheet.Cells(row, fcol).Style.Font.SetFromFont(New System.Drawing.Font("Arial", 10, System.Drawing.FontStyle.Regular))
                xlWorksheet.Cells(row, fcol).Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center
                xlWorksheet.Cells(row, fcol).Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
            Next
            For i As Integer = fcol + 1 To mcol
                xlWorksheet.Cells(row, i).Style.Font.SetFromFont(New System.Drawing.Font("Arial", 10, System.Drawing.FontStyle.Regular))
                xlWorksheet.Cells(row, i).Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
            Next
            xlWorksheet.Cells(row, 1, row, mcol).Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
            xlWorksheet.Cells(row, 1, row, mcol).Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.FromArgb(192, 192, 192))

            For Each wp As KeyValuePair(Of String, System.Collections.Generic.SortedDictionary(Of String, Integer)) In matrix
                row += 1
                Dim col As Integer = 1
                xlWorksheet.Cells(row, col).Value = wp.Key
                xlWorksheet.Cells(row, col).Style.Font.SetFromFont(New System.Drawing.Font("Arial", 10, System.Drawing.FontStyle.Regular))
                xlWorksheet.Cells(row, col).Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
                For Each flor As KeyValuePair(Of String, Integer) In wp.Value
                    col += 1
                    xlWorksheet.Cells(row, col).Value = flor.Value
                    xlWorksheet.Cells(row, col).Style.Font.SetFromFont(New System.Drawing.Font("Arial", 10, System.Drawing.FontStyle.Regular))
                    xlWorksheet.Cells(row, col).Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
                Next
                For i As Integer = col + 1 To mcol
                    xlWorksheet.Cells(row, i).Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
                Next
            Next

            'xlWorksheet.Cells(hrow, 1, row, fcol).AutoFitColumns()

            If mcol < fcol Then
                mcol = fcol
            End If
            If mrow < row Then
                mrow = row
            Else
                For i As Integer = row + 1 To mrow
                    For j As Integer = 1 To mcol
                        xlWorksheet.Cells(i, j).Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin)
                    Next
                Next
            End If
            xlWorksheet.Cells(hrow + 1, 1, mrow, 1).Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
            xlWorksheet.Cells(hrow + 1, 1, mrow, 1).Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.FromArgb(255, 204, 153))

            For i As Integer = 1 To mcol
                xlWorksheet.Column(i).Width = 6.0
            Next
            xlWorksheet.PrinterSettings.PrintArea = xlWorksheet.Cells(1, 1, mrow, mcol)
            xlWorksheet.PrinterSettings.PaperSize = ePaperSize.Letter
            xlWorksheet.PrinterSettings.FitToPage = True

            If p_lv Is Nothing Then
                If p_floor = "" Then
                    xlPackage.Workbook.Properties.Title = "RCMS FP Count for building " & v_building
                Else
                    xlPackage.Workbook.Properties.Title = "RCMS FP Count for building " & v_building & ", floor " & p_floor
                    xlPackage.Workbook.Properties.SetCustomPropertyValue("RCMS Floor", p_floor)
                End If
            Else
                xlPackage.Workbook.Properties.Title = "RCMS FP Count for AutoCAD drawing " & name
                xlPackage.Workbook.Properties.SetCustomPropertyValue("AutoCAD drawing", name)
            End If
            xlPackage.Workbook.Properties.SetCustomPropertyValue("RCMS Building", v_building)
            xlPackage.Workbook.Properties.SetCustomPropertyValue("RCMS AutoCAD Version", v_no & " " & v_date)
            xlPackage.Save()
        End Using
        MsgBox("Created spreadsheet file " & fname, MsgBoxStyle.Information, "RCMS AutoCAD")
    End Sub
    Public Sub CLDS_Excel_CableList(ByVal p_clv As System.Windows.Forms.ListView, ByVal p_flv As System.Windows.Forms.ListView, ByVal p_building As String, Optional ByVal p_floor As String = "")
        Dim name As String = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Name
        name = Path.GetFileNameWithoutExtension(name)
        Dim fname As String
        If p_clv Is Nothing Then
            fname = System.Environment.ExpandEnvironmentVariables(pPrefs.p_excl) & "\rcms_" & p_building & "_cable.xlsx"
        Else
            fname = System.Environment.ExpandEnvironmentVariables(pPrefs.p_excl) & "\rcms_" & name & "_cable.xlsx"
        End If
        If File.Exists(fname) Then
            File.Delete(fname)
        End If
        Dim finfo As FileInfo = New FileInfo(fname)
        Dim v_building As String = pRCMSDialog.tbBuilding.Text
        Dim xlPackage As New ExcelPackage(finfo)
        Using xlPackage
            Dim xlWorksheet As ExcelWorksheet = xlPackage.Workbook.Worksheets.Add(p_building & " Cables")
            Dim row As Integer = 1
            Dim hrow As Integer = 0
            Dim hcol As Integer = 10
            Dim fcol As Integer = 4
            xlWorksheet.Cells(row, 1).Value = "Building " & v_building

            Using r As ExcelRange = xlWorksheet.Cells(row, 1, row, hcol)
                'r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Britannic Bold", 22, System.Drawing.FontStyle.Italic))
                r.Style.Font.Color.SetColor(System.Drawing.Color.White)
                'r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.CenterContinuous
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
                r.Style.Fill.BackgroundColor.SetColor(pPrefs.c_texc)
            End Using
            If Not p_clv Is Nothing Then
                row += 1
                xlWorksheet.Cells(row, 1).Value = "Drawing " & name
                Using r As ExcelRange = xlWorksheet.Cells(row, 1, row, hcol)
                    'r.Merge = True
                    r.Style.Font.SetFromFont(New System.Drawing.Font("Britannic Bold", 22, System.Drawing.FontStyle.Italic))
                    r.Style.Font.Color.SetColor(System.Drawing.Color.White)
                    'r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.CenterContinuous
                    r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                    r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
                    r.Style.Fill.BackgroundColor.SetColor(pPrefs.c_texc)
                End Using
            End If
            row += 1
            xlWorksheet.Cells(row, 1).Value = "Cable List"
            Using r As ExcelRange = xlWorksheet.Cells(row, 1, row, hcol)
                'r.Merge = True
                r.Style.Font.SetFromFont(New System.Drawing.Font("Britannic Bold", 18, System.Drawing.FontStyle.Italic))
                r.Style.Font.Color.SetColor(System.Drawing.Color.Black)
                'r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.CenterContinuous
                r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left
                r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
                r.Style.Fill.BackgroundColor.SetColor(pPrefs.c_hexc)
            End Using
            row += 2
            hrow = row
            xlWorksheet.Cells(row, 1).Value = "Cable ID"
            xlWorksheet.Cells(row, 2).Value = "FP ID"
            xlWorksheet.Cells(row, 3).Value = "Project"
            xlWorksheet.Cells(row, 4).Value = "Phase"
            xlWorksheet.Cells(row, 1, row, fcol).Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid
            xlWorksheet.Cells(row, 1, row, fcol).Style.Fill.BackgroundColor.SetColor(pPrefs.c_hexc)
            xlWorksheet.Cells(row, 1, row, fcol).Style.Font.Bold = True

            If p_clv Is Nothing Then
                Dim r As Integer = 0
                For j As Integer = 1 To 1000
                    Dim arr As String(,)
                    Dim acc As Collection
                    Dim p_id As String = "BUILDING=""" & p_building & """"
                    If p_floor <> "" Then p_id = p_id & " FLOOR=""" & p_floor & """"
                    If pRCMSDialog.cxFilterProject.Text <> "" Then p_id = p_id & " PROJECT=""" & pRCMSDialog.cxFilterProject.Text & """"
                    If pRCMSDialog.cxFilterPhase.Text <> "" Then p_id = p_id & " PHASE=""" & pRCMSDialog.cxFilterPhase.Text & """"
                    Dim n As Integer = CLDS_Query(Nothing, j, "EXCEL", "CABLELIST", p_id, arr, acc)
                    If n <= 0 Then
                        Exit For
                    End If
                    For i As Integer = 1 To n - 1
                        Dim cableID As String = arr(acc("CABLELIST_CBID"), i)
                        Dim fpID As String = arr(acc("CABLELIST_FPID"), i)
                        Dim fpproj As String = arr(acc("CABLELIST_PROJECT"), i)
                        Dim fpphase As String = arr(acc("CABLELIST_PHASE"), i)
                        row += 1
                        xlWorksheet.Cells(row, 1).Value = cableID
                        xlWorksheet.Cells(row, 2).Value = fpID
                        xlWorksheet.Cells(row, 3).Value = fpproj
                        xlWorksheet.Cells(row, 4).Value = fpphase
                    Next
                Next
            Else
                For Each lvi As System.Windows.Forms.ListViewItem In p_clv.Items
                    Dim cableID As String = lvi.Text
                    Dim FPID As String = lvi.SubItems(1).Text
                    Dim flvi As System.Windows.Forms.ListViewItem = p_flv.FindItemWithText(FPID)
                    Dim fpproj As String = ""
                    Dim fpphase As String = ""
                    If Not flvi Is Nothing Then
                        fpproj = flvi.SubItems(5).Text
                        fpphase = flvi.SubItems(6).Text
                    End If
                    If (pRCMSDialog.cxFilterProject.Text = "" Or fpproj = pRCMSDialog.cxFilterProject.Text) And (pRCMSDialog.cxFilterPhase.Text = "" Or fpphase = pRCMSDialog.cxFilterPhase.Text) Then
                        row += 1
                        xlWorksheet.Cells(row, 1).Value = cableID
                        xlWorksheet.Cells(row, 2).Value = FPID
                        xlWorksheet.Cells(row, 3).Value = fpproj
                        xlWorksheet.Cells(row, 4).Value = fpphase
                    End If
                Next
            End If
            xlWorksheet.Cells(hrow, 1, row, fcol).AutoFitColumns()
            xlWorksheet.Cells(hrow, 1, hrow, fcol).AutoFilter = True
            If p_clv Is Nothing Then
                If p_floor = "" Then
                    xlPackage.Workbook.Properties.Title = "RCMS Cable List for building " & v_building
                Else
                    xlPackage.Workbook.Properties.Title = "RCMS Cable List for building " & v_building & ", floor " & p_floor
                    xlPackage.Workbook.Properties.SetCustomPropertyValue("RCMS Floor", p_floor)
                End If
            Else
                xlPackage.Workbook.Properties.Title = "RCMS Cable List for AutoCAD drawing " & name
                xlPackage.Workbook.Properties.SetCustomPropertyValue("AutoCAD drawing", name)
            End If
            xlPackage.Workbook.Properties.SetCustomPropertyValue("RCMS Building", v_building)
            xlPackage.Workbook.Properties.SetCustomPropertyValue("RCMS AutoCAD Version", v_no & " " & v_date)
            xlPackage.Save()
        End Using
        MsgBox("Created spreadsheet file " & fname, MsgBoxStyle.Information, "RCMS AutoCAD")
    End Sub
    Public Sub CLDS_Excel_Report(ByVal p_dialog As RCMS_Container)
        If p_dialog.pBuilding = "" Or p_dialog.pBuilding = "-" Then
            MsgBox("Drawing is not associated with any building", MsgBoxStyle.Critical, "RCMS AutoCAD")
            Exit Sub
        End If
        Dim f As String = ""
        If p_dialog.rbRptFPList.Checked Then
            f = "FPList"
        ElseIf p_dialog.rbRptCableList.Checked Then
            f = "CableList"
        ElseIf p_dialog.rbRptCount.Checked Then
            f = "Count"
        Else
            MsgBox("Please select report format", MsgBoxStyle.Critical, "RCMS AutoCAD")
            Exit Sub
        End If
        Dim s As String = ""
        If p_dialog.rbScopeBuilding.Checked Then
            s = "Building"
        ElseIf p_dialog.rbScopeDrawing.Checked Then
            s = "Drawing"
        ElseIf p_dialog.rbScopeFloor.Checked Then
            s = "Floor"
            If p_dialog.cxScopeFloor.Text = "" Or p_dialog.cxScopeFloor.Text = "-" Then
                MsgBox("Please select building floor", MsgBoxStyle.Critical, "RCMS AutoCAD")
                Exit Sub
            End If
        Else
            MsgBox("Please select report scope", MsgBoxStyle.Critical, "RCMS AutoCAD")
            Exit Sub
        End If
        If f = "FPList" Then
            If s = "Building" Then
                CLDS_Excel_FPList(Nothing, p_dialog.pBuilding, "")
            ElseIf s = "Drawing" Then
                CLDS_ShowList(p_dialog, False)
                CLDS_Excel_FPList(p_dialog.lvFaceplates, p_dialog.pBuilding, "")
            Else
                CLDS_Excel_FPList(Nothing, p_dialog.pBuilding, p_dialog.cxScopeFloor.Text)
            End If
        ElseIf f = "CableList" Then
            If s = "Building" Then
                CLDS_Excel_CableList(Nothing, Nothing, p_dialog.pBuilding, "")
            ElseIf s = "Drawing" Then
                CLDS_ShowList(p_dialog, False)
                CLDS_Excel_CableList(p_dialog.lvCables, p_dialog.lvFaceplates, p_dialog.pBuilding, "")
            Else
                CLDS_Excel_CableList(Nothing, Nothing, p_dialog.pBuilding, p_dialog.cxScopeFloor.Text)
            End If
        Else
            If s = "Building" Then
                CLDS_Excel_Count(Nothing, p_dialog.pBuilding, "")
            ElseIf s = "Drawing" Then
                CLDS_ShowList(p_dialog, False)
                CLDS_Excel_Count(p_dialog.lvFaceplates, p_dialog.pBuilding, "")
            Else
                CLDS_Excel_Count(p_dialog.lvFaceplates, p_dialog.pBuilding, p_dialog.cxScopeFloor.Text)
            End If
        End If
    End Sub
#End Region
#Region "Palette functions"
    Public Sub CLDS_RCMSPalette(ByVal p_dialog As RCMS_Container, Optional ByVal p_title As String = "RCMS")
        If p_palette Is Nothing Then
            p_palette = New Autodesk.AutoCAD.Windows.PaletteSet("", p_palguid)
            '            AddHandler p_palette.SizeChanged, AddressOf PaletteResizeHandler
        End If
        p_palette.Name = p_title
        p_palette.Add("Connection", p_dialog)
        p_palette.Visible = True
        p_palette.MinimumSize = New System.Drawing.Size(320, 400)
    End Sub
#End Region
#Region "Commands"
    <Autodesk.AutoCAD.Runtime.CommandMethod("CLDS_ProjectNames")> _
    Public Sub CLDS_ProjectNames()
        Dim pn As String = CLDS_Static_Utils.CLDS_ProjectNames
        Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
        ed.WriteMessage(vbLf & "Available PROJECTNAMEs: " & pn & vbLf)
    End Sub
    <Autodesk.AutoCAD.Runtime.CommandMethod("CLDS_RegisterRCMS")> _
    Public Sub CLDS_RegisterRCMS()
        DemandLoading.RegistryUpdate.RegisterForDemandLoading(True)
    End Sub
    <Autodesk.AutoCAD.Runtime.CommandMethod("CLDS_UnregisterRCMS")> _
    Public Sub CLDS_UnregisterRCMS()
        DemandLoading.RegistryUpdate.UnregisterForDemandLoading()
    End Sub
    <Autodesk.AutoCAD.Runtime.CommandMethod("CLDS_RCMS")> _
    Public Sub CLDS_DoRCMS()
        Dim doc As Document
        Dim ed As Editor
        doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        ed = doc.Editor
        Dim id As String = Microsoft.VisualBasic.FileIO.FileSystem.GetName(doc.Name)
        Dim p As New RCMS_Drawing_Properties, z As RCMS_Drawing_Properties
        p.v_file = doc.Name & ".xml"
        z = p.LoadProperties()
        If z Is Nothing Then
            If Not p_palette Is Nothing Then
                p_palette.Visible = False
            End If
            Exit Sub
        End If
        Me.pProps = p
        pPrefs.LoadPreferences()
        CLDS_DropConnection()
        Dim x As Boolean = CLDS_URLConnection(True)
        If Not x Or CMAPI Is Nothing Then
            ed.WriteMessage(vbLf & "Unable to connect to CMPIC")
            If Not p_palette Is Nothing Then
                p_palette.Visible = False
            End If
            Exit Sub
        End If
        CLDS_GetProjectDefaults()
        If tokens.Count = 0 Then
            If Not p_palette Is Nothing Then
                p_palette.Visible = False
            End If
            Exit Sub
        End If
        If p_palette Is Nothing Then
            Dim c As RCMS_Container = New RCMS_Container
            c.Initialize(Me)
            If pProps.v_projectname = "" Then
                c.lbConnected.Text = "Connected"
            Else
                c.lbConnected.Text = "Connected to " & UCase(pProps.v_projectname)
            End If
            Me.pRCMSDialog = c
            ' CLDS_RCMSPalette(c, "RCMS " & v_no & " " & v_date)
            CLDS_RCMSPalette(c, "RCMS AutoCAD")
            pPrefs.x_vist = v_no & " " & v_date
            ' AddHandler Application.DocumentManager.DocumentActivated, AddressOf docColDocAct
            ' AddHandler Application.DocumentManager.DocumentToBeDeactivated, AddressOf docColDocDeact
            If pPrefs.g_file = "" Then
                c.btSavePrefs.Enabled = True
            End If
        Else
            p_palette.Visible = True
            Me.pRCMSDialog.Initialize(Me)
            ' RemovePaletteValues()
        End If
    End Sub
#End Region

End Class
